Puppy Linux Discussion Forum Forum Index Puppy Linux Discussion Forum
Puppy HOME page : puppylinux.com
"THE" alternative forum : puppylinux.info
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

The time now is Tue 02 Sep 2014, 18:09
All times are UTC - 4
 Forum index » Off-Topic Area » Programming
GtkDialog - tips
Post new topic   Reply to topic View previous topic :: View next topic
Page 1 of 64 [949 Posts]   Goto page: 1, 2, 3, ..., 62, 63, 64 Next
Author Message
zigbert


Joined: 29 Mar 2006
Posts: 5701
Location: Valåmoen, Norway

PostPosted: Wed 11 Feb 2009, 13:32    Post subject:  GtkDialog - tips  

GtkDialog
GtkDialog lets your bash script run in gui.
Here's some tips for learning more about gtkdialog.

This info is based on input from many people. I'm trying to throw it all together. Please share your knowledge.
Some tips require the latest gtkdialog. Thanks to thunor who has continued the development of gtkdialog. If you intend to compile the latest gtkdialog, read this.



###################################################################################
INDEX
1.) Where to start - links to documentation and examples.
2.) Syntax - How to use variables in the code.
3.) Let the script return data - Choose a proper coding structure.
4.) Let external code act on your gtkdialog gui
5.) The benefits of a config file
--> Set default status of Radiobuttons, Comboboxes...
--> How to store window size/placement
6.) Speed issues - Let your turtle run
7.) Extended use of widgets - Undocumented features
8.) Advanced Syntax - make your code readable
--> Comments in your code.
--> Include code if.......
9.) Tips and tricks
--> How to change the gui without restarting the app
--> Control the icon/label of menuitems.
--> Understand the alignment.
--> Transparent background.
--> Window header icon.
--> Tooltips.
--> Refresh image
--> Right-click menu.
--> Scroll text.
--> Drag'n drop.
--> Hotkeys.
--> Set a fixed size of a progressbar.
--> Define unique gtk-theme.
--> Override JWM-settings - skip taskbar, sticky, layer, border
--> Let entry accept (some) numbers only.
--> MIME.
--> Checkbox with image
--> Use a splash screen.
--> Press 'Enter' instead of clicking the 'Ok' button.



###################################################################################
1.) Where to start
###################################################################################

>> First stop should always be the new homepage of gtkdialog. Thunor is offering a reference guide for the widgets.

>> The examples is often easier to understand. They are located in /usr/share/doc/gtkdialog/examples, (in Puppy you need the dev_save.sfs file installed).

>> The general documentation of gtkdialog is poor, but it's a start. You'll find it in /usr/share/doc/gtkdialog/gtkdialog.txt.
The same info with better formatting on the web.

>> The command 'gtkdialog --help' shows available parameters.



###################################################################################
2.) Syntax - How to use variables in the code.
###################################################################################

The basics of building a simple gui is told by the links in chapter 1.) You should have played a little bit before you continue.

About QUOTES
To show content of a variable in the gtkdialog code, we need to quote the variable in the gtkdialog code.
Code:
#!/bin/bash

TEXT='Hello world'

export script='
<text>
  <label>Content of variable is: '"$TEXT"'</label>
</text>'

gtkdialog --program=script

Now in other words - Because this is important!!!

First realize that you put all the gtkdialog code into a variable - ie MAIN_WINDOW or Psync:
export Psync="<window title=\"Psync\"...........</window>"
if you now try to 'echo Psync' you'll get
<window title="Psync"...........</window>
which is correct code. But if you used ' instead of ", like this:
export Psync='<window title=\"Psync\"...........</window>'
you'll get
<window title=\"Psync\"...........</window>
This will give a syntax error.
export Psync='<window title="Psync"...........</window>'
will give correct syntax

Now using a variable like this:
TITLE=Psync
export Psync=
"<window title=\"$TITLE\"...........</window>"

returns
<window title="Psync"...........</window>
while
export Psync='<window title="$TITLE"...........</window>'
returns
<window title="$TITLE"...........</window>
and not the content of variable TITLE

Now return to the first example about quotes. This example combines the use of ' and ".



###################################################################################
3.) Let the script return data - Choose a proper coding structure
###################################################################################

While first step is to get a dialog show up on your screen, the next step is obvious to get something valuable information back when user act on your gui. I think the easiest way is to divide guis into different groups. - Simple, Complex and Projects.

>> Simple
The simple dialogs are waiting for the user to give response for the question he/she has got:
- Do you want to continue?
- Please choose item in list?
- ...
When user click on the yes/no/cancel/ok-button the dialog exits and the script continues to evaluate the user input. Here is an example:
Code:
#!/bin/bash
export script='
<vbox>
  <text><label>Are you sure?</label></text>
  <hbox>
    <button no></button>
    <button yes><action>EXIT:sure</action></button>
  </hbox>
</vbox>'

I=$IFS; IFS=""
for STATEMENTS in  $(gtkdialog --program=script); do
   eval $STATEMENTS
done
IFS=$I

[ $EXIT = sure ] && gxmessage 'You are sure'


>> Complex
For more complex dialogs, we want to keep the gui alive even if the user click on something, so using an EXIT value is not the right choice. Calling pre-defined functions from inside the gtkdialog gui is a handy way to do this. We must remember to export all functions before executing our gui.

Code:
#!/bin/sh

now () {
   date > /tmp/date
}
export -f now

export script='
<vbox>
  <entry>
    <variable>ENTRY_DATE</variable>
    <input>cat /tmp/date</input>
  </entry>
  <button>
    <label>Refresh</label>
    <action>now</action>
    <action>refresh:ENTRY_DATE</action>
  </button>
</vbox>'

gtkdialog -p script


>> Project
When your project grows and its complexity makes it hard to work with, it's time to consider another approach. Split code into several files might be much more usable when working with your code. Group familiar functions into one file... In this example, the function-file must be saved in /root/test to work. Instead of sending <action> to EXIT, we send it to the file with the function 'now'.

NOTE, that I don't use an ordinary function (like the previous example), but a case command instead. The benefits are faster loading of your app since it does not read your functions into memory. But the greatest pro is that you can edit the function while the gui is running. The downside are slower execution of the function.

Function file
Code:
#!/bin/sh

case $1 in
-now)
   date > /tmp/date
   exit;;
esac

Main file
Code:
export script='
<vbox>
  <entry>
    <variable>ENTRY_DATE</variable>
    <input>cat /tmp/date</input>
  </entry>
  <button>
    <label>Refresh</label>
    <action>/root/test -now</action>
    <action>refresh:ENTRY_DATE</action>
  </button>
</vbox>'

I=$IFS; IFS=""
for STATEMENTS in  $(gtkdialog -p script); do
   eval $STATEMENTS
done
IFS=$I



###################################################################################
4.) Let external code act on your gtkdialog gui
###################################################################################

>> If you want a second gtkdialog-gui to act on your main gui. You simply "launch" the second gui from the main gui. The negative about this solution is that before showing the main gui, it has to load all the launchable scripts. This means slower startup.

Code:
#!/bin/sh

export launch_me='
<button>
 <input file stock="gtk-refresh"></input>
 <action>Refresh:DATE</action>
</button>'

export box='
<vbox>
 <entry><input>date</input><variable>DATE</variable></entry>
 <button><label>launch</label><action type="launch">launch_me</action></button>
</vbox>'

gtkdialog -p box


>> Imagine that you start a background process to calculate the content of <list>. It will take too long to wait for the result before showing the gui. Imagine that you want to update content in a gui from a complete alien app. Okay, here's the trick.....

Gtkdialog updates a progressbar with info from standard output. Most common are 'cat' and 'echo' command. First 'echo "text in bar"' (optional), then 'echo 50' or whatever % integer to define how long the process is come. When a progressbar recieve 100% done ('echo 100'), it activates its <actions>. So....as long as % is below 100, the actions are not run, but as soon as you 'echo 100' it will execute your defined actions. What is very good, is that you now can 'echo 0', and start all over again. Last stage is to define if you want the progressbar shown in your gui. add visible="false" to make it invisible.

Here is a simple example of a clock
Code:
#!/bin/sh

export box='
 <vbox>
  <progressbar visible="false">
   <input>while [ A != B ]; do sleep 0.5; P=`cat /tmp/p`;   echo $P; echo 100 > /tmp/p; done</input>
   <action>refresh:ENTRY</action>
   <action>echo 99 > /tmp/p</action>
  </progressbar>
  <entry>
   <variable>ENTRY</variable>
   <input>date +%H:%M:%S</input>
  </entry>
 </vbox>'

gtkdialog -p box


>> If you want a frequent refreshing of a widget, the <timer> widget was introduced in gtkdialog 0.7.21.
<timer milliseconds="true" interval="500" visible="false">
Gtkdialog misses a tailbox widget, but using this solution it is easy to build our own tailbox.

>> Both <timer> and <progressbar> widgets uses cpu-power, and in a complex gui this could be a real pitfall. Here follows an explanation of how it is solved in Pmusic. It is a way to update a complex gui on non-user actions. User-actions is mouse-clicks and key-entries, and is the common way to interact between user and gui. An example of updating the gui on a non-user-action in Pmusic is the loading of id3-tags for files shown in the file-browser....

When clicking on a directory, the browser field refreshes and shows the content of the new directory. Now, Pmusic continues with a background process to read the id3 information of the files. When finished, the browser field should be updated by the new info. - Without the user to click anywhere.

The solution is to either use a <progressbar> which runs its <action> when reaches 100% or a <timer> which acts at a given interval. Older Pmusic releases used the <progressbar> solution while recent code uses a <timer>. Both solutions has the downside that they uses an amount of cpu power. In a complex gui with several non-user actions this could end up with several cpu-hungry <timers> updating their unique widget(s) of the gui.

Pmusic has used 2 <timers> running constantly to update their defined gui-part. You might think that 1 <timer> would be enough, - it could refresh all wanted widgets - it wouldn't harm if the refreshing didn't change anything. BUT, refreshing has an effect on the focus handling. It simply resets the focus, which means that:
- scrolling in <table> is moved to top.
- what you are about to write in an <entry> is cleared.
- Your selected item in the <tree> is not selected anymore
- ...

The idea of Pmusic 2.4.0 was to update all kinds of trackinfo (meta-tags, lyrics, albumart, discography, ...) when a new track starts playing. This would not be possible with the underlaying event-handling in Pmusic because it would either suck you cpu-power (with several <timers>), or a global refreshing would make it impossible to be a user (because of focus issues). Also, there is a fact that too many refreshing <action> on a <timer> will increase cpu-usage as well.

So the solution has been to add ONE <timer>, which refreshes a small set of <checkboxes> that (if true) refreshes a single or group of widgets.

<checkboxes> can be set true or false by their <input file>, so we can simply 'echo true' to its <input file>. The <timer> runs its <actions> each second, and the <checkbox> will be refreshed by its <input file>. The code could look like this:
Code:
<checkbox visible="false">
 <label>a</label>
 <variable>UPDATE_GUI</variable>
 <input>cat /path/UPDATE_GUI</input>
 <action>if true refresh:PLAYLIST</action>
 <action>if true refresh:ARTWORK</action>
 <action>if true refresh:BUTTON_PLAY</action>
 <action>if true echo false > /path/UPDATE_GUI</action>
</checkbox>

All actions will run only if value is true. To avoid more than one refreshing we reset <input file> and the <checkbox> value to false. Now it will be silent until next time we 'echo true > inputfile'.

Example script here


###################################################################################
5.) The benefits of a config file
###################################################################################

A config file is a nice way to store the settings in your program. At next startup, it will show setting like you left them last time.

Set default status of Radiobuttons, Comboboxes...
>> By default, gtkdialog always activates the first radiobutton and the first list-item for combobox.

An easy way to use a config file is to run it like an ordinary bash-script, and include variable definition in it. It is most common to keep config files in home directory as a hidden file ($HOME/.testrc). The file might look like this:
Code:
COMBOBOX="item 3"
ENTRY="default text"
RADIOBUTTON1="false"
RADIOBUTTON2="true"


Now let's go to the main script. For the radiobuttons and the entry, we set the <default> tag to the coresponding variable in the config file. Since the combobox doesn't support the <default> tag, we need a workaround. We simply builds the combobox item-list so show our saved variable first.

Code:
#!/bin/bash
#in case no testc file (first run), build the file
[ ! -s $HOME/.testrc ] && echo -e -n 'COMBOBOX="item 3"\nENTRY="default text"\nRADIOBUTTON1="false"\nRADIOBUTTON2="true"\n' > $HOME/.testrc
. $HOME/.testrc

#define combobox list items
COMBOBOX_ITEMS="<item>$COMBOBOX</item>" #stored value should be first in list
for I in 1 2 3 4; do COMBOBOX_ITEMS=`echo "$COMBOBOX_ITEMS<item>item $I</item>"`; done

export main="
<window title=\"The benefits of a config file\">
 <vbox>
  <frame The first item of list is the default choice in a Combobox>
   <combobox>
    <variable>COMBOBOX</variable>
    $COMBOBOX_ITEMS
   </combobox>
  </frame>
  <frame If nothing else is set, the first radiobutton is the active one>
   <radiobutton>
    <variable>RADIOBUTTON1</variable>
    <label>Yes I am</label>
    <default>$RADIOBUTTON1</default>
   </radiobutton>
   <radiobutton>
    <variable>RADIOBUTTON2</variable>
    <label>No I'm not</label>
    <default>$RADIOBUTTON2</default>
   </radiobutton>
  </frame>
  <frame Fetch entry-value from config file>
   <entry>
    <variable>ENTRY</variable>
    <default>$ENTRY</default>
   </entry>
  </frame>
  <hbox>
   <button ok></button>
  </hbox>
 </vbox>
</window>"

gtkdialog -p main > $HOME/.testrc


The last codeline redirects output (variable values) to our config file instead of to the terminal.
Note that line 2 starts with a dot. It makes a huge different if you skip it.
. $HOME/.config --> run script as a childprocess as the main process. The variable values in the config file are reachable for the main script.
$HOME/.config --> run script as a new process as the main process. The variable values in the config file will NOT be reachable for the main script.

How to store window size/placement
>> This example shows how we can save settings for window size and placement for next startup. Be also aware that this solution makes it possible to let user rescale gui smaller than the default size. Normally you define the size of ie. a <tree>, and the user can only resize the gui larger, but when using <window default_height="$HEIGHT" default_width="$WIDTH">, you don't need to define <height> and <width> for the tree widget.
Code:
#! /bin/bash

save_geometry (){
   XWININFO=`xwininfo -stats -name SizeMe`
   HEIGHT=`echo "$XWININFO" | grep 'Height:' | awk '{print $2}'`
   WIDTH=`echo "$XWININFO" | grep 'Width:' | awk '{print $2}'`
   X1=`echo "$XWININFO" | grep 'Absolute upper-left X' | awk '{print $4}'`
   Y1=`echo "$XWININFO" | grep 'Absolute upper-left Y' | awk '{print $4}'`
   X2=`echo "$XWININFO" | grep 'Relative upper-left X' | awk '{print $4}'`
   Y2=`echo "$XWININFO" | grep 'Relative upper-left Y' | awk '{print $4}'`
   X=$(($X1-$X2))
   Y=$(($Y1-$Y2))
   echo "export HEIGHT=$HEIGHT"   > /tmp/geometry
   echo "export WIDTH=$WIDTH"      >> /tmp/geometry
   echo "export X=$X"            >> /tmp/geometry
   echo "export Y=$Y"            >> /tmp/geometry
   chmod 700 /tmp/geometry
}

export -f save_geometry
[ -f /tmp/geometry ] && . /tmp/geometry

export DIALOG="
<window title=\"SizeMe\" default_height=\"$HEIGHT\" default_width=\"$WIDTH\">
  <vbox>
    <frame>
      <text>
        <label>If you resize or move this window, it will be remembered for next time.</label>
      </text>
    </frame>
    <hbox>
      <button ok>
      </button>
    </hbox>
  </vbox>
  <action signal=\"hide\">save_geometry</action>
</window>"
gtkdialog --program=DIALOG --geometry +"$X"+"$Y"



>> Another approach for size/placement is to make a call of your app from cli.
Code:
RIGHT=14 DOWN=36 WIDTH=80 HEIGHT=80 # define variables with defaults

GUI='
 <vbox>
  <button cancel></button>
 </vbox>'
gtkdialog -p GUI -G ${1-${WIDTH}x${HEIGHT}+${RIGHT}+${DOWN}}
/tmp/gui 200x200+500+500 or
/tmp/gui 75x75 or
/tmp/gui +0+0 or
/tmp/gui for the default geometry



###################################################################################
6.) Speed issues - Let your turtle run
###################################################################################

Gtkdialog is not a fast gui-lib. If you are building a gui where speed matters, please check the following notes.

>> For an unknown reason, it is much faster to start your gtkdialog-xml-code from a file than from a variable.
gtkdialog --file=filename
gtkdialog --program=variable
The file alternative is highly recommended if your xml-code is getting complex.

>> If you include a long list in your gui, you should consider to use the <table> widget instead of <tree> or <list>. While <tree> and <list> first reads content of list, and then render it, the <table> renders while content is read.

>> Progressbars can suck your cpu-power. Adding a reasonable sleep value in the loop helps a lot.

>> Run large calculations as a background process. Pmusic builtin filebrowser (version 0.9) first shows songs in the directory, then it starts a background process to find meta informations of the songs. When finished, it renders the song-list once again, now with complete information. How to use a background process with gtkdialog is explained in the chapter 'Let external code act on your gtkdialog gui'.

>> Even if gtkdialog is slow, your bash-code might make it MUCH slower. Be careful with the use of subshells, and slow commands as sed, ps, expr, cat ... This is of course most important when building a loop.

The pairs of code shows how to do the same operation in 2 different ways. The speed differs a lot. First an example why avoid 'cat', then why never use 'expr' if speed matters. My system needed 4 seconds to calculate 1+1 thousand times with 'expr'. Using the builtin bash command it took 'no time'.
Code:
# time for I in $(seq 1 1000); do B="`cat /tmp/tmp`"; done
real    0m3.095s
# time `IFS=$'\n'; for I in $(seq 1 1000); do B=($(<"/tmp/tmp")); done`
real    0m0.927s


# time for I in $(seq 1 1000); do expr 1 + 1 > /dev/null; done
real    0m4.286s
# time for I in $(seq 1 1000); do A=$((1+1)); done
real    0m0.032s


>> There are many ways of building a gui. The pictures below shows the builtin filebrowser/filesearch in Pburn 2 (left) and Pburn 3. The code has shrunk from 3110 to 997 chars. It does exactly the same, and the speed improvement are notable.

. . . . . . .


###################################################################################
7.) Extended use of widgets - Undocumented features
###################################################################################
Generals
>> Add tooltips.
<hbox tooltip-text=" This is the text ">...</hbox>
>> Widgets might be invisible.
<progressbar visible="false">...</progressbar>
>> Define how much space the widget should take.
<text height-request="50" width-request="200">...</text>
>> Avoid tab-key to give focus
<edit can-focus="no">...</edit>
>> Align widget. xalign/yalign may hold 0 (left), 1 (right) and 2 (center). xalign/yalign works for most widgets. For button/progressbar they describe placement of label rather than widget itself.
<text xalign="0">...</text>

<window>
>> prevent user from resizing the gui.
<window allow-grow="false">
>> Shrink window smaller than widgets requires to show up.
<window allow-shrink="true">

<text>
>> For more advanced text layout, here is a good catch.
>> Justify aligment to right (1), center (2), left (3).
<text justify="2">
>> Angle the text
<text angle="45">
>> Force one-line text
<text wrap="false">
<text single-line-mode="true">
>> Set underline pattern
<text label="Underline me with an useless pattern" pattern="__ __ __ __ __ __ _"></text>

<button>
>> You can skip the button decoration.
<button relief="2">...</button>
>> The image doesn't need to be left of label. It can be left/right/above/below. Values 0-3. Be aware that this seems to work only for icons in the gtk-stock.
<button use-stock="true" image-position="3">...</button>
>> Use gtk-stock values
<button use-stock="true" label="gtk-quit"></button>
>> Hotkey is set in 2 ways
<button use-stock="true" label="gtk-cancel">...</button>
<button use-underline="true"><label>_Cancel</label>...</button>
>> Scale icon
<button height-request="50" width-request="80"><input file>file.jpg</input><height>40</height><width>70</width></button>

<entry>
>> Give entry focus
<entry text="Focus is here" is-focus="true"></entry>
>> Not editable
<entry editable="false"></entry>
>> Password - show input text as ******
<entry visibility="false"></entry>
>> Alternative way to define default text
<entry text="default string">
>> Show progress in entry - or simply change the color of the entry background
<entry progress-fraction="0.5">
>> Icons in <entry>
<entry primary-icon-activatable="true" primary-icon-stock="gtk-refresh" secondary-icon-activatable="true" secondary-icon-stock="gtk-clear"
>> Caps lock control
<entry caps-lock-warning="true"></entry>

<notebook>
>> You can define which tab should be active by default. "0" represent tab1, "1" represent tab2 ...
<notebook page="1">...</notebook>
>> Tabs can be shown at Top/Bottom/Left/Right. Values from 0-3
<notebook tab-pos="3">...</notebook>
>> Tabs can chosen in right-click menu
<notebook enable-popup="true">...</notebook>

<edit>
>> insert margins
<edit left-margin="20">...</edit>
>> avoid user input
<edit editable="no">...</edit>

<pixmap>
>> Scale image
<pixmap><input file>file.jpg</input><height>40</height><width>70</width></pixmap>

<progressbar>
>> Avoid window to autoscale because of too much text in progressbar. You can truncate text at left (1), at right (3) or in the middle (2) by the ellipsize tag.
<progressbar text="Truncated the text in the middle" ellipsize="2"></progressbar>
>> Define the text alignment by text-xalign and text-yalign tag. try out values from 0-3 for left, right and center.
<progressbar text-xalign="1" text-yalign="1">
>> Do not show text
<progressbar show-text="false">
>> Alternative bar outfit. - view blocks
<progressbar bar-style="1">
>> Do not truncate result to block-size.
<progressbar discrete-blocks="25">
>> Set orientation
0 - Horizontal - left to right.
1 - Horizontal - right to left.
2 - Vertical - bottom to top.
3 - Vertical - top to bottom.
<progressbar orientation="3">




###################################################################################
8.) Advanced Syntax - make your code readable
###################################################################################

Comments in your code
Gtkdialog doesn't support comments in its xml code. But if we convert all comments before execution, it works. The reason why I use double hash (##) for my comments, is because colors in a <span> tag might be defined as 'red' or '#FF0000'. The latter would be removed by using a single hash.

Code:
#!/bin/sh

XML='
<vbox>                     ##this is how to comment your xml code.
  <text height-request="50">   ##force the text to take more space.
   <label>Hello</label>
  </text>
  <hbox>                  ##hbox to align button to the right.
    <button ok></button>      ##button ok is fetched from the gtk stock.
  </hbox>
</vbox>'

export GUI="`echo "$XML" | sed -e 's/##.*//'`"
gtkdialog -p GUI



Include code if.......
It is possible to build the gtkdialog out of many small pieces. Every piece is a variable and are put together when exporting the gtkdialog code. It is easy to think that a button should have different label depending on ........ Or like in the following example, - include a button if file/app/.. exists. Instead of defining all these pieces before the actual gtkdialog code, it is much more human readable if you define all 'inside' the gtkdialog code.

Code:
script='
<vbox>
 <hbox>
  <text>
   <label>Yes button added if file /root/testfile exists</label>
  </text>'
  [ -f /root/testfile ];then script=${script}'<button yes></button>'
  script=${script}'
  <button no>
  </button>
 </hbox>
</vbox>'

export SCRIPT="$script"
gtkdialog --program=SCRIPT





###################################################################################
9.) Tips and tricks
###################################################################################


How to change the gui without restarting the app
>> Recent Gtkdialog allows to hide/show widgets, To hide many widgets at once, you can hide a <hbox> or <vbox>. This will hide all widgets inside the box.

>>Another approach is to use the notebook attributes <notebook show-tabs="false" show-border="false">. Using several tabs in a notebook with hidden header, we can simulate a gui rerender. The only thing that is happening is that we switch tab, but since the user can't see those, he will be fooled...
More info here.


Control the icon/label of menuitems
>> If you have met problems to show a certain icon and at the same time give it an unique label, this will illustrate how it is recommended to be implemented for the benefit of anyone and everyone.
Code:
<menuitem stock="gtk-undo" label="'$LOC118'" accel-key="0x07a" accel-mods="4">
   <action>. '$APPDIR'/func -undo</action>
   <action>refresh:PLAYLIST</action>
</menuitem>'

Doing it this way makes GTK+ deal with the left-to-right and right-to-left internationalisation of the icons if applicable. You might be thinking that this isn't going to work because GTK+ will make a stock label "_Undo" and it will, but straight afterwards it will update the label with $LOC118 and additionally because it was initially a stock label, "use-underline" is already true so you can use underscores in your custom text.


Understand the alignment
>> Gtkdialog tends to align objects to the right side of the window. Exceptions are radiobuttons and checkboxes which are aligned to the left. It is easy to center whatever object in your gui. Here's some alignment explanation:
- <hbox><button>...</button></hbox> will place button to the right.
- <button>...</button> and button will fill whole line.
- <hbox homogeneous=true><button>...</button></hbox> will place button in horizontal center.
- <hbox homogeneous=true><vbox homogeneous=true><button>...</button></vbox></hbox> will place button in center both vertical and horizontal.
- <hbox><text xalign="0">...</text></hbox> will place text at left. xalign/yalign may hold 0 (left), 1 (right) and 2 (center). xalign/yalign works for other widgets as well. For buttons they describe placement of label rather than button itself.

>> Using vertical rows can be troublesome, because often, the label defines the width of the objects. This leads to different width and it all looks crappy. You can override this by the attribute <vbox width-request="x">....</vbox>, where x represent the number of pixels for the width of the row. There is also a 'height-request' attribute.

>> Insert empty gap
Static:
Code:
<text width-chars="40" height-request="120"><label>""</label></text>

Dynamic: (align one button to the left, another to the right)
Code:
<hbox space-expand="false" space-fill="false">
  <button yes></button>
  <hbox space-expand="true" space-fill="true"><text><label>""</label></text></hbox>
  <button no></button>
</hbox>



Transparent background
>> akash_rawal has made a solution for building gtkdialog desklets.
check out this


Window header icon
>> You can add your own icon if you place it in any of the folders in /usr/share/icons/hicolor/. (System links also work)
ie. /usr/share/icons/hicolor/48x48/apps/games48.png
Now, run this command in the terminal to refresh the icon cache;
Code:
gtk-update-icon-cache -f -i /usr/share/icons/hicolor

Your gtkdialog code would look like this;
Code:
<window title="A GTKDialog" icon-name="games48" resizable="false" decorated="true">



Tooltips
>> Gtkdialog does support tooltips, even if it's not documented. All widgets can use the tooltips, - also <hbox> and <vbox>.
<button tooltip-text=" tooltips text ">......</button>
>> It is also possible to use advanced text layout.
<button tooltip-markup="<span background='yellow'><b><i> press alt m </i><b><span>">......</button>


Refresh image
>> Gtkdialog can refresh an image in a <pixmap> widget without restarting the gui. Since the <input file> is static, we must change its content (by copy another file), and then refresh.
Code:
#!/bin/bash

export MAIN='
<window>
 <pixmap>
  <variable>IMAGE</variable>
  <input file>/root/image1.png</input>
 </pixmap>
 <button>
  <label>Change image</label>
   <action>cp -f /root/image2.png /root/image1.png</action>
   <action type="refresh">IMAGE</action>
  </button>
</window>'

gtkdialog --center --program=MAIN



Right-click menu
>> By using this code, gtkdialog will allow external menus.


Scroll text
>> This example shows scrolling text in a <text> widget. This will work for other widgets as well.
Code:
#!/bin/sh
export MSG="This is a test... I repeat: This is a test... "
export GTKBOX='
<vbox width-request="300">
 <text>
  <variable>MSG</variable>
  <input>echo -en "${MSG:2}${MSG:0:2}"</input>
 </text>
 <timer milliseconds="true" interval="200" visible="false">
  <action type="refresh">MSG</action>
 </timer>
</vbox>'
gtkdialog4 -p GTKBOX



Drag'n drop
>> Gtkdialog supports drag'n drop from filebrowser (rox) to <entry> widget.
Code:
export test="
<entry accept=\"directory\" width-request=\"300\">
 <default>Drag a directory from Rox</default>
</entry>"
gtkdialog -p test



>> But this is not all....The next script shows how to move items in list by drag'n drop. This example shows only one list, but it is of course possible to drag between 2 lists.
Code:
#!/bin/sh

move (){
   PRESS_EVENT="`cat /tmp/PRESS_EVENT`"
   grep -Fv "$PRESS_EVENT" /tmp/list > /tmp/tmp
   grep -Fm1 -B500 "$TREE" /tmp/tmp | grep -v "$TREE" > /tmp/tmp1
   echo "$PRESS_EVENT" >> /tmp/tmp1
   grep -Fm1 -A500 "$TREE" /tmp/tmp >> /tmp/tmp1
   mv -f /tmp/tmp1 /tmp/list
}

export -f move
ls -1 /usr/share/backgrounds > /tmp/list

export test="
<tree rules_hint=\"true\" hover-selection=\"true\" tooltip-text=\"Drag'n drop items to move them in list\">
 <label>Backgrounds</label>
 <input>cat /tmp/list</input>
 <variable>TREE</variable>
 <height>300</height><width>200</width>
 <action signal=\"button-press-event\">echo \$TREE > /tmp/PRESS_EVENT</action>
 <action signal=\"button-release-event\">move</action>
 <action signal=\"button-release-event\">refresh:TREE</action>
</tree>"
gtkdialog -p test



Hotkeys
>> An <action> signal inside the <window> widget gives the most direct hotkey
<action signal="key-press-event" condition="command_is_true( [ $(( ${KEY_MOD} & 5 )) = 5 ] && [ $KEY_RAW = 0x1b ] && echo true )">Refresh:varDATE</action>
SHIFT's state is held by by 0th bit and CTRL state by 2nd bit of $KEY_MOD variable (?????C?S) , so, in order to read their state correctly, we need to discard the rest of bits by logical AND: $(( $KEY_MOD & 5 )). If we would want SHIFT alone, it would be $(( $KEY_MOD & 1)) = 1, only CTRL - $(( $KEY_MOD & 4 )) = 4 and so on.
see this forum thread for more depth

>> Menuitems can set both accelerator key and modifier (SHIFT is 1, CTRL is 4 and ALT is 8 ). For a full list of accelerator key values check this
<menuitem stock-id="gtk-quit" accel-key="0x51" accel-mods="4">

>> You can activate buttons by pressing keyboard combinations. simply add the attribute 'use-underline'. If set, an underline in the text indicates the next character should be used for the mnemonic accelerator key.
<button use-underline="true"><label>_Refresh</label></button>
The defined char in the <label> + 'alt' key will activate given <action>.


Set a fixed size of a progressbar
>> Progressbars are by default rather big. But it's not that easy to define the width of a progressbar. To do this you have to combine some attributes.
Code:
<hbox>
 <vbox>
  <progressbar width-request="100" height-request="20" Expand="no" Fill="no">
   <input>echo 70; echo small bar</input>
  </progressbar>
 </vbox>
</hbox>



Define unique gtk-theme
>> Sometimes it is nice to change the gtktheme just for my app. Like this I get more options for my gtkdialog script.

Gtkdialog does not support monospace in the <edit> widget, but I can make it work by adding a unique gtk-theme only for my app. The best way to this is to add my new gtk-theme on top of the already existing. Now my gtk-theme can hold ONLY information about monospace, else it will use gtk-settings specified by user.

By giving the text-widget a name (see example), it is possible to have a gtk-theme for only this uniqe text string. This also works for text in widgets like <entry>.

Code:
#!/bin/bash
echo 'style "specialmono"
{
  font_name="Mono 12"
}
widget "*mono" style "specialmono"
class "GtkText*" style "specialmono"' > /tmp/gtkrc_mono

export GTK2_RC_FILES=/tmp/gtkrc_mono:/root/.gtkrc-2.0

export test_app="
<vbox>
  <text name=\"mono\"><label>This text-widget uses monospace font....</label></text>
  <text><label>...while this text-widget don't.</label></text>
  <edit><default>All edit-widgets gets monospace.</default></edit>
</vbox>"
gtkdialog --program=test_app



Override JWM-settings - skip taskbar, sticky, layer, border
This is how to override default settings in your JWM configuration.

Your gtkdialog gui must be called with the --class parameter
Code:
gtkdialog --class=APPLET -f myfile
Then this code must be in your jwm configuration file - $HOME/.jwmrc (to be set permanently, it must be added to /etc/xdg/templates/_root_.jwmrc)
Code:
<Group>
 <Class>APPLET</Class>
 <Option>nolist</Option>
 <Option>sticky</Option>
 <Option>noborder</Option>
 <Option>layer:12</Option>
</Group>
>> The option 'nolist' does avoid your app showing up in the taskbar.
>> The option 'sticky' shows your app on all desktops.
>> The option 'noborder' is equal to the gtkdialog attribute <window decorated="false">.
>> The option 'layer:x' defines if other windows should cover your app, or if it should be on top. layers can be 0-12 where 12 is the on-top setting.


Let entry accept (some) numbers only
>> The following example shows how to limit the user input to a <entry>. Useful for 'all' kinds of settings.
Code:
#!/bin/bash
 
export MAIN_DIALOG='
<vbox>
    <text>
      <label>"Enter a number (text will default to 0)"</label>
    </text>
    <entry editable="true" allow-empty="false">
      <input>case $ENTRY in [0-9]*) echo $ENTRY;; *) echo 0;; esac</input>
      <variable>ENTRY</variable>
      <action signal="focus-out-event">refresh:ENTRY</action>
    </entry>
    <text>
      <label>"Enter a number within [5,15], otherwise:
        input will be capped at 15,
        floored at 5,
        or set to 10 in case of text input"</label>
    </text>
    <entry editable="true" allow-empty="false">
      <input>A=$ENTRY2; case $A in [0-9]*) [[ $A -gt 15 ]] && echo 15 || [[ $A -lt 5 ]] && echo 5 || echo $A ;; *) echo 10;; esac</input>
      <variable>ENTRY2</variable>
      <action signal="focus-out-event">refresh:ENTRY2</action>
    </entry>
  <button ok></button>
</vbox>'

gtkdialog -p MAIN_DIALOG
unset MAIN_DIALOG



MIME
>> What should happen when user double-click on an image-file in your gui. In some cases it is logical to show the image in an image-viewer. But....it is no need of linking all kinds of extensions to different programs. - It is already done by the filebrowser. Puppy uses 'rox' and if you execute 'rox /path/image.png' the image will show up in the defined viewer. Just as simple as that.



Checkbox with image
>> This example shows how to add a image beside the label of a checkbox. Be aware that this tecnique only works for gtk stock-items.
Code:
<checkbox use-stock="true" label="gtk-fullscreen" image-position="1"
tooltip-text="checkbox derives from button ...">
</checkbox>
<button use-stock="true" label="gtk-quit">
</button>




Use a splash screen
>> A splash screen could be useful if the startup time is increasing. The delay may occur of 2 reasons. There are several startup processes, or the gtkdialog code is heavy. The latter case makes it necessary to close the splash-window first when the main window is drawn on screen. We use the <window> signal 'show' to determine when the splash should be closed.
Code:
#!/bin/sh

#Splash
echo 0 > /tmp/splash
export SPLASH='
<window title="PCC" icon-name="gtk-preferences" resizable="false" decorated="false">'"
<vbox>
 <pixmap><input file>/usr/share/midi-icons/configuration48.png</input></pixmap>
 <text height-request=\"50\" use-markup=\"true\"><label>\"<b><span size='"'x-large'"' color='"'orange'"'>Puppy Control Center</span></b>\"</label></text>"'
 <progressbar visible="false">
  <label>nn</label>
  <input>while [ "$M" != "100" ]; do M=`cat /tmp/splash`; echo $M; usleep 500000; done</input>
  <action type="exit">Ready</action>
 </progressbar>
</vbox></window>'
gtkdialog -p SPLASH --center &

sleep 2 #well, this is to simulate some startup processes....

export GUI='
<window title="PCC" icon-name="gtk-preferences" width-request="800">
<vbox>
  <text height-request="200">
   <label>Hello, welcome to the Puppy Control Center</label>
  </text>
  <hbox>
    <button ok></button>
  </hbox>
</vbox>
 <action signal="show">echo 100 > /tmp/splash</action>
</window>'

gtkdialog -p GUI


>> Mave has made an attempt to replace yaf-splash using gtkdialog. Yaf-splash is not supporting UTF-8, and has given some issues when translation to some languages. Read more here


Press 'Enter' instead of clicking the 'Ok' button
>> When writing input to the app it is much easier to just press the 'Enter' key to activate <action>.

Code:
#!/bin/sh
export ok_box='
<window>
 <vbox>
  <entry activates_default="true"><default>press _enter_ to activate OK-button</default></entry>
  <hbox>
   <button can-default="true" has-default="true" use-stock="true">
    <input file icon="gtk-ok"></input>
    <label>Ok</label>
    <action>EXIT:ok</action>
   </button>
  </hbox>
 </vbox>
</window>'
gtkdialog -p ok_box

Last edited by zigbert on Sun 06 Jul 2014, 19:34; edited 156 times in total
Back to top
View user's profile Send private message Visit poster's website 
big_bass

Joined: 13 Aug 2007
Posts: 1747

PostPosted: Wed 11 Feb 2009, 14:09    Post subject:  

Zigbert

A very big thanks for sharing

a long needed thread

now ,I'll return to my seat and listen
for your updates




big_bass

Last edited by big_bass on Wed 11 Feb 2009, 17:29; edited 1 time in total
Back to top
View user's profile Send private message 
zigbert


Joined: 29 Mar 2006
Posts: 5701
Location: Valåmoen, Norway

PostPosted: Wed 11 Feb 2009, 17:00    Post subject:  

big_bass
link fixed.

Thank you
Sigmund

_________________
Stardust resources
Back to top
View user's profile Send private message Visit poster's website 
big_bass

Joined: 13 Aug 2007
Posts: 1747

PostPosted: Fri 13 Feb 2009, 01:34    Post subject:  

well with woof in the making
thought to test on slackware 12.1
and get gtkdialog working



I dont know why puppy calls it gtkdialog3
I have to figure out what was the compiled versions original version #

anyway
all the official snippets worked

and only your gtkdialog_widget_audioplayer
works outside of puppy

slackware needs ffmpeg a a several dependent libs


*dont try the progress bar from puppy you kill your connection
on slackware too : D pkgtool >re run the network script
dougal's progess bar looks nice so I want to figure it out


tip: change the permissions to non executable
to keep things safe

its up and running on slackare now using these
ftp://linux.pte.hu/pub/gtkdialog/gtkdialog-0.7.20.tar.gz
ftp://linux.pte.hu/pub/gtkdialog/GUIcompletion-0.1.5.tar.gz


just a progress report to let you know I am using your thread productively

big_bass
Back to top
View user's profile Send private message 
jrb


Joined: 11 Dec 2007
Posts: 1034
Location: Smithers, BC, Canada

PostPosted: Sat 21 Feb 2009, 01:42    Post subject:  

I would like to have a checkbox that would output to a list in a file that could then be used in a "for" statement. I'm afraid I don't understand the output of these GUI's, or any for that matter, although I have been able to modify other people's to suit my needs.

Any help or references would be appreciated.

Thanks, J
Back to top
View user's profile Send private message 
zigbert


Joined: 29 Mar 2006
Posts: 5701
Location: Valåmoen, Norway

PostPosted: Sat 21 Feb 2009, 08:56    Post subject:  

If you test the latest pwidgets-1.5 there is a cluster-plugin included. If I understand you correct, that simple code will show you what you want. /root/.pwidgets/plugins/cluster/cluster


Sigmund

_________________
Stardust resources
Back to top
View user's profile Send private message Visit poster's website 
jrb


Joined: 11 Dec 2007
Posts: 1034
Location: Smithers, BC, Canada

PostPosted: Sat 21 Feb 2009, 12:04    Post subject:  

Thanks zigbert,
Now that you point it out, the pwidgets available widget chooser does exactly what I want to do, and I have been staring at it for weeks. Rolling Eyes

Now I will see about puzzling out an adaptation.

Thanks again, J
Back to top
View user's profile Send private message 
01micko


Joined: 11 Oct 2008
Posts: 7797
Location: qld

PostPosted: Wed 22 Apr 2009, 06:19    Post subject:  

Ah ok...

I've been learning a lot here, but some still complain, notably ttuuxxx about 'Gtkdialog'.

But I see it is being addressed... http://www.murga-linux.com/puppy/viewtopic.php?p=297840#297840

Good!

Love it!

Mick

_________________
Woof Mailing List | keep the faith Cool |
Back to top
View user's profile Send private message Visit poster's website 
zigbert


Joined: 29 Mar 2006
Posts: 5701
Location: Valåmoen, Norway

PostPosted: Tue 30 Jun 2009, 12:30    Post subject:  

Added new widget: volume level
_________________
Stardust resources
Back to top
View user's profile Send private message Visit poster's website 
big_bass

Joined: 13 Aug 2007
Posts: 1747

PostPosted: Tue 30 Jun 2009, 12:45    Post subject:  

Hey zigbert

that app is very small could be posted directly
to the forum at 1kb

note because the download limit is blocking the link for me to try it


I like code that can be used again even outside of puppy
so code snippets are treats

making them all portable and self contained not version dependent
lends itself to other distros too Cool

thanks for posting



Joe

_________________
debian wheezy ,linux mint, slackware I use them all and they all have good points
Mint would be best for general users though
Back to top
View user's profile Send private message 
big_bass

Joined: 13 Aug 2007
Posts: 1747

PostPosted: Wed 01 Jul 2009, 13:22    Post subject:  

links are working now thanks

Joe

_________________
debian wheezy ,linux mint, slackware I use them all and they all have good points
Mint would be best for general users though
Back to top
View user's profile Send private message 
zigbert


Joined: 29 Mar 2006
Posts: 5701
Location: Valåmoen, Norway

PostPosted: Thu 30 Jul 2009, 12:00    Post subject:  

Heavy updated !
See main post

_________________
Stardust resources
Back to top
View user's profile Send private message Visit poster's website 
potong

Joined: 06 Mar 2009
Posts: 88

PostPosted: Wed 05 Aug 2009, 01:19    Post subject: One thing leads to another
Subject description: Undocumented Properties
 

I've been learning the ins and outs of gtkdialog3 for a while but put it aside to study genie. Not much documentation for either genie or vala and so I went back to basics and reviewed the GTK+ documentation from http://library.gnome.org/devel/gtk/stable/gtkobjects.html. Whilst trying to convert the GTK+ offical c tutorial examples to genie I had an epiphany.

Widgets in gtkdialog3 can accept attributes (read properties) but little documentation was about and the examples hinted that there was more under the hood than shown. I also glanced at the glade interface and saw more evidence of props there but how to use them?

The answer ... try it and see!
Code:

#!/bin/bash
a_function()
{
    echo "you pressed ${1}"
}
b_function()
{
    echo "you pressed ${1}=${!1}"
}

# variables to be exported
export BUTTON1="_plain tooltip" BUTTON2="_markup tooltip"
# functions can be exported too!
export -f a_function b_function

export GUI="
<window title=\"Tooltip Test\" window-position=\"1\">
  <vbox>
    <button use-underline=\"true\" label=\"$BUTTON1\" tooltip-text=\" press alt p \" xalign=\"0.3\" yalign=\"0.7\" width-request=\"100\" height-request=\"200\">
      <action signal=\"clicked\">a_function BUTTON1</action>
    </button>
    <button use-underline=\"true\" tooltip-markup=\"<span background='yellow'><b> press alt m </b></span>\">
      <label>$BUTTON2</label>
      <action signal=\"map-event\">echo \"this button was mapped before it was clicked\"</action>
      <action signal=\"clicked\">b_function BUTTON2</action>
    </button>
    <button use-underline=\"true\" has_focus=\"true\" use-stock=\"true\" label=\"gtk-cancel\" tooltip-text=\" press alt c or enter to close \"></button>
    <frame frames can only have text :(>
      <text use-underline=\"true\" use-markup=\"true\" label=\"<span foreground='blue'><b>N.B.</b> _labels <i>can have tooltips</i> <u>too!...but no actions :-()</u></span>\" tooltip-text=\" press alt l\">
      </text>
    </frame>
  </vbox>
</window>
"
gtkdialog3 -d -p GUI


I've probably only scratched the surface.

Question: How to use complex properties i.e. GtkBorder, GtkWidget etc

potong

N.B. some properties are enumerated and can be replaced by integer values e.g in a window widget window-position=\"1\" means centre the window and window-position=\"2\" means follow cursor. A tip is when reading the documentation a tooltip indicates the property type
Also note that widgets have hierarchy and inherit from them (check out GtkWidget for example)

Last edited by potong on Sun 14 Feb 2010, 04:52; edited 1 time in total
Back to top
View user's profile Send private message 
zigbert


Joined: 29 Mar 2006
Posts: 5701
Location: Valåmoen, Norway

PostPosted: Wed 05 Aug 2009, 02:09    Post subject:  

Wow !!!!!!

Give us more, give us more Very Happy Very Happy Very Happy

I will rewrite my code, and the examples above.
Thanks a lot


Sigmund

_________________
Stardust resources
Back to top
View user's profile Send private message Visit poster's website 
zigbert


Joined: 29 Mar 2006
Posts: 5701
Location: Valåmoen, Norway

PostPosted: Wed 05 Aug 2009, 03:04    Post subject:  

potong
Code:
<action signal=\"map-event\">echo \"this button was mapped before it was clicked\"</action>
What does a map-event do. What is it good for?

I tried to define hot-keys for my menu/menuitems but it failed. Have you any knowledge?????


Sigmund

_________________
Stardust resources
Back to top
View user's profile Send private message Visit poster's website 
Display posts from previous:   Sort by:   
Page 1 of 64 [949 Posts]   Goto page: 1, 2, 3, ..., 62, 63, 64 Next
Post new topic   Reply to topic View previous topic :: View next topic
 Forum index » Off-Topic Area » Programming
Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group
[ Time: 0.2961s ][ Queries: 13 (0.0134s) ][ GZIP on ]