added menubar example
This commit is contained in:
parent
92f788236e
commit
d7aa177796
2 changed files with 230 additions and 0 deletions
125
README.adoc
125
README.adoc
|
|
@ -811,6 +811,131 @@ these conversions are rare, and because gintro use no converters at all still, w
|
||||||
an explicit proc.) The use of cstringArray as third parameter for proc setAccelsForAction()
|
an explicit proc.) The use of cstringArray as third parameter for proc setAccelsForAction()
|
||||||
is a bit ugly, we have to fix that later.
|
is a bit ugly, we have to fix that later.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
== GMenu with GActions
|
||||||
|
|
||||||
|
The following example shows how we can define GActions and bind them to Menus, Buttons
|
||||||
|
and Keyboard shortcuts. Examples for stateless actions (quit), for toggle actions (spellcheck)
|
||||||
|
and for statefull actions (text justify) are provided.
|
||||||
|
|
||||||
|
Note that the following code is not a direct translation of an existing example, but
|
||||||
|
a collections of informations from various sources, so
|
||||||
|
it may contain bugs or not fully optimal code.
|
||||||
|
|
||||||
|
[[menubar.nim]]
|
||||||
|
[source, nim]
|
||||||
|
.menubar.nim
|
||||||
|
----
|
||||||
|
# https://developer.gnome.org/glib/stable/glib-GVariant.html
|
||||||
|
# https://developer.gnome.org/glib/stable/glib-GVariantType.html
|
||||||
|
# https://wiki.gnome.org/HowDoI/GMenu
|
||||||
|
# https://wiki.gnome.org/HowDoI/GAction
|
||||||
|
# nim c menubar.nim
|
||||||
|
import gintro/[gtk, glib, gobject, gio]
|
||||||
|
from strutils import `%`, format
|
||||||
|
|
||||||
|
# https://github.com/GNOME/glib/blob/master/gio/tests/gapplication-example-actions.c
|
||||||
|
proc activateToggleAction(action: SimpleAction; parameter: Variant; app: Application) =
|
||||||
|
app.hold # hold/release taken over from C example, there may be reasons...
|
||||||
|
block:
|
||||||
|
echo format("action $1 activated", action.name)
|
||||||
|
let state: Variant = action.state
|
||||||
|
let b = state.getBoolean
|
||||||
|
action.state = newVariantBoolean(not b)
|
||||||
|
echo format("state change $1 -> $2", b, not b)
|
||||||
|
app.release
|
||||||
|
|
||||||
|
proc activateStatefulAction(action: SimpleAction; parameter: Variant; app: Application) =
|
||||||
|
app.hold
|
||||||
|
block:
|
||||||
|
echo format("action $1 activated", action.name)
|
||||||
|
let state: Variant = action.state
|
||||||
|
var l: uint64
|
||||||
|
let oldState = state.getString(l) # yes uint64 parameter is a bit ugly
|
||||||
|
let newState = parameter.getString(l)
|
||||||
|
action.state = newVariantString(newState)
|
||||||
|
echo format("state change $1 -> $2", oldState, newState)
|
||||||
|
app.release
|
||||||
|
|
||||||
|
proc quitProgram(action: SimpleAction; parameter: Variant; app: Application) =
|
||||||
|
quit(app)
|
||||||
|
|
||||||
|
proc appStartup(app: Application) =
|
||||||
|
let quit = newSimpleAction("quit") # here we create the actions for whole app
|
||||||
|
connect(quit, "activate", quitProgram, app)
|
||||||
|
app.addAction(quit)
|
||||||
|
|
||||||
|
let menu = gio.newMenu() # root of all menus
|
||||||
|
block: # plain stateless menu
|
||||||
|
let subMenu = gio.newMenu()
|
||||||
|
menu.appendSubMenu("Application", submenu)
|
||||||
|
# let section = gio.newMenu() # no separating section needed here
|
||||||
|
# submenu.appendSection(nil, section)
|
||||||
|
# section.append("Quit", "app.quit")
|
||||||
|
submenu.append("Quit", "app.quit")
|
||||||
|
|
||||||
|
block: #stateful menu with radio items
|
||||||
|
let subMenu = gio.newMenu()
|
||||||
|
menu.appendSubMenu("Layout", submenu)
|
||||||
|
let subMenu2 = gio.newMenu()
|
||||||
|
submenu.appendSubMenu("justify", submenu2)
|
||||||
|
let section = gio.newMenu()
|
||||||
|
submenu2.appendSection(nil, section)
|
||||||
|
section.append("left", "win.justify::left")
|
||||||
|
section.append("center", "win.justify::center")
|
||||||
|
section.append("right", "win.justify::right")
|
||||||
|
|
||||||
|
block: # and finally a toggle menu
|
||||||
|
let subMenu = gio.newMenu()
|
||||||
|
menu.appendSubMenu("Spelling", submenu)
|
||||||
|
let section = gio.newMenu()
|
||||||
|
submenu.appendSection(nil, section)
|
||||||
|
section.append("Check", "win.toggleSpellCheck")
|
||||||
|
# finally add the menubar
|
||||||
|
setMenuBar(app, menu)
|
||||||
|
|
||||||
|
proc appActivate(app: Application) =
|
||||||
|
let window = newApplicationWindow(app)
|
||||||
|
window.title = "GTK3 App with Menubar"
|
||||||
|
window.defaultSize = (500, 200)
|
||||||
|
window.position = WindowPosition.center
|
||||||
|
block: # creat the window related actions
|
||||||
|
let v = newVariantBoolean(true)
|
||||||
|
let spellCheck = newSimpleActionStateful("toggleSpellCheck", nil, v)
|
||||||
|
connect(spellCheck, "activate", activateToggleAction, app)
|
||||||
|
window.actionMap.addAction(spellCheck)
|
||||||
|
block:
|
||||||
|
let v = newVariantString("left") # default value and
|
||||||
|
let vt = newVariantType("s") # string (value type)
|
||||||
|
let justifyAction = newSimpleActionStateful("justify", vt, v)
|
||||||
|
connect(justifyAction, "activate", activateStatefulAction, app)
|
||||||
|
window.actionMap.addAction(justifyAction)
|
||||||
|
let button = newButton()
|
||||||
|
button.label = "Justify Center"
|
||||||
|
#window.add(button) # do not add it here already: (menubar:10010): Gtk-WARNING **:
|
||||||
|
# 22:00:33.230: actionhelper: action win.justify can't be activated due to
|
||||||
|
# parameter type mismatch (parameter type s, target type NULL)
|
||||||
|
button.setDetailedActionName("win.justify::center")
|
||||||
|
#button.setActionName("app.quit") # for a stateless action
|
||||||
|
var h: cstringArray = allocCstringArray(["<Control><Shift>R"]) # ugly
|
||||||
|
setAccelsForAction(app, "win.justify::right", h)
|
||||||
|
deallocCStringArray(h)
|
||||||
|
window.add(button)
|
||||||
|
showAll(window)
|
||||||
|
|
||||||
|
proc main =
|
||||||
|
let app = newApplication("app.example")
|
||||||
|
connect(app, "startup", appStartup)
|
||||||
|
connect(app, "activate", appActivate)
|
||||||
|
echo "GTK Version $1.$2.$3" % [$majorVersion(), $minorVersion(), $microVersion()]
|
||||||
|
let status = run(app)
|
||||||
|
quit(status)
|
||||||
|
|
||||||
|
main()
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
== Drawing with Cairo graphics library
|
== Drawing with Cairo graphics library
|
||||||
|
|
||||||
The next example shows how we can use the cairo graphics library for drawing on a DrawingArea widget,
|
The next example shows how we can use the cairo graphics library for drawing on a DrawingArea widget,
|
||||||
|
|
|
||||||
105
examples/menubar.nim
Normal file
105
examples/menubar.nim
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
# https://developer.gnome.org/glib/stable/glib-GVariant.html
|
||||||
|
# https://developer.gnome.org/glib/stable/glib-GVariantType.html
|
||||||
|
# https://wiki.gnome.org/HowDoI/GMenu
|
||||||
|
# https://wiki.gnome.org/HowDoI/GAction
|
||||||
|
# nim c menubar.nim
|
||||||
|
import gintro/[gtk, glib, gobject, gio]
|
||||||
|
from strutils import `%`, format
|
||||||
|
|
||||||
|
# https://github.com/GNOME/glib/blob/master/gio/tests/gapplication-example-actions.c
|
||||||
|
proc activateToggleAction(action: SimpleAction; parameter: Variant; app: Application) =
|
||||||
|
app.hold # hold/release taken over from C example, there may be reasons...
|
||||||
|
block:
|
||||||
|
echo format("action $1 activated", action.name)
|
||||||
|
let state: Variant = action.state
|
||||||
|
let b = state.getBoolean
|
||||||
|
action.state = newVariantBoolean(not b)
|
||||||
|
echo format("state change $1 -> $2", b, not b)
|
||||||
|
app.release
|
||||||
|
|
||||||
|
proc activateStatefulAction(action: SimpleAction; parameter: Variant; app: Application) =
|
||||||
|
app.hold
|
||||||
|
block:
|
||||||
|
echo format("action $1 activated", action.name)
|
||||||
|
let state: Variant = action.state
|
||||||
|
var l: uint64
|
||||||
|
let oldState = state.getString(l) # yes uint64 parameter is a bit ugly
|
||||||
|
let newState = parameter.getString(l)
|
||||||
|
action.state = newVariantString(newState)
|
||||||
|
echo format("state change $1 -> $2", oldState, newState)
|
||||||
|
app.release
|
||||||
|
|
||||||
|
proc quitProgram(action: SimpleAction; parameter: Variant; app: Application) =
|
||||||
|
quit(app)
|
||||||
|
|
||||||
|
proc appStartup(app: Application) =
|
||||||
|
let quit = newSimpleAction("quit") # here we create the actions for whole app
|
||||||
|
connect(quit, "activate", quitProgram, app)
|
||||||
|
app.addAction(quit)
|
||||||
|
|
||||||
|
let menu = gio.newMenu() # root of all menus
|
||||||
|
block: # plain stateless menu
|
||||||
|
let subMenu = gio.newMenu()
|
||||||
|
menu.appendSubMenu("Application", submenu)
|
||||||
|
# let section = gio.newMenu() # no separating section needed here
|
||||||
|
# submenu.appendSection(nil, section)
|
||||||
|
# section.append("Quit", "app.quit")
|
||||||
|
submenu.append("Quit", "app.quit")
|
||||||
|
|
||||||
|
block: #stateful menu with radio items
|
||||||
|
let subMenu = gio.newMenu()
|
||||||
|
menu.appendSubMenu("Layout", submenu)
|
||||||
|
let subMenu2 = gio.newMenu()
|
||||||
|
submenu.appendSubMenu("justify", submenu2)
|
||||||
|
let section = gio.newMenu()
|
||||||
|
submenu2.appendSection(nil, section)
|
||||||
|
section.append("left", "win.justify::left")
|
||||||
|
section.append("center", "win.justify::center")
|
||||||
|
section.append("right", "win.justify::right")
|
||||||
|
|
||||||
|
block: # and finally a toggle menu
|
||||||
|
let subMenu = gio.newMenu()
|
||||||
|
menu.appendSubMenu("Spelling", submenu)
|
||||||
|
let section = gio.newMenu()
|
||||||
|
submenu.appendSection(nil, section)
|
||||||
|
section.append("Check", "win.toggleSpellCheck")
|
||||||
|
# finally add the menubar
|
||||||
|
setMenuBar(app, menu)
|
||||||
|
|
||||||
|
proc appActivate(app: Application) =
|
||||||
|
let window = newApplicationWindow(app)
|
||||||
|
window.title = "GTK3 App with Menubar"
|
||||||
|
window.defaultSize = (500, 200)
|
||||||
|
window.position = WindowPosition.center
|
||||||
|
block: # creat the window related actions
|
||||||
|
let v = newVariantBoolean(true)
|
||||||
|
let spellCheck = newSimpleActionStateful("toggleSpellCheck", nil, v)
|
||||||
|
connect(spellCheck, "activate", activateToggleAction, app)
|
||||||
|
window.actionMap.addAction(spellCheck)
|
||||||
|
block:
|
||||||
|
let v = newVariantString("left") # default value and
|
||||||
|
let vt = newVariantType("s") # string (value type)
|
||||||
|
let justifyAction = newSimpleActionStateful("justify", vt, v)
|
||||||
|
connect(justifyAction, "activate", activateStatefulAction, app)
|
||||||
|
window.actionMap.addAction(justifyAction)
|
||||||
|
let button = newButton()
|
||||||
|
button.label = "Justify Center"
|
||||||
|
#window.add(button) # do not add it here already: (menubar:10010): Gtk-WARNING **: 22:00:33.230: actionhelper:
|
||||||
|
# action win.justify can't be activated due to parameter type mismatch (parameter type s, target type NULL)
|
||||||
|
button.setDetailedActionName("win.justify::center")
|
||||||
|
#button.setActionName("app.quit") # for a stateless action
|
||||||
|
var h: cstringArray = allocCstringArray(["<Control><Shift>R"]) # ugly
|
||||||
|
setAccelsForAction(app, "win.justify::right", h)
|
||||||
|
deallocCStringArray(h)
|
||||||
|
window.add(button)
|
||||||
|
showAll(window)
|
||||||
|
|
||||||
|
proc main =
|
||||||
|
let app = newApplication("app.example")
|
||||||
|
connect(app, "startup", appStartup)
|
||||||
|
connect(app, "activate", appActivate)
|
||||||
|
echo "GTK Version $1.$2.$3" % [$majorVersion(), $minorVersion(), $microVersion()]
|
||||||
|
let status = run(app)
|
||||||
|
quit(status)
|
||||||
|
|
||||||
|
main()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue