226a4ea784
This code was (and is still) commented out but it *would* trigger a "stack buffer overflow" error *if* uncommented. The new code demonstrates how a binary object (Fl_Preferences 'bed') can be dumped to a preferences file in binary format (if activated).
481 lines
13 KiB
Plaintext
481 lines
13 KiB
Plaintext
# data file for the Fltk User Interface Designer (fluid)
|
|
version 1.0400
|
|
i18n_type 1
|
|
i18n_include {<stdio.h>}
|
|
i18n_conditional {}
|
|
i18n_gnu_function gettext
|
|
i18n_gnu_static_function gettext_noop
|
|
header_name {.h}
|
|
code_name {.cxx}
|
|
snap {
|
|
ver 1
|
|
current_suite FLTK
|
|
current_preset 0
|
|
}
|
|
comment {About test/preferences:
|
|
|
|
The preferences app shows two features of FLTK and FLUID.
|
|
|
|
The Fl_Preferences class is used as a storage for user
|
|
settings between app launches. Fl_Preferences can store
|
|
small amounts of arbitrary data in an .ini file format
|
|
which can be retrieved again at the next app launch.
|
|
|
|
The FLUID setup uses GNU gettext for internationalisation
|
|
(i18n). FLUID finds the texts that need to be translated
|
|
and writes them into .po files that can be processed by
|
|
the GNU gettext tools. FLUID produces source code that
|
|
will translate all text into the current locale when
|
|
generating the UI.
|
|
|
|
|
|
In this small example, 'getttext' is only emulated.} {in_source not_in_header
|
|
}
|
|
|
|
decl {\#include <FL/Fl_Preferences.H>} {public local
|
|
}
|
|
|
|
decl {\#include <stdio.h>} {public local
|
|
}
|
|
|
|
decl {\#include <stdlib.h>} {private local
|
|
}
|
|
|
|
decl {\#include <FL/filename.H>} {private local
|
|
}
|
|
|
|
decl {\#include <FL/fl_ask.H>} {private local
|
|
}
|
|
|
|
decl {\#define _(text) gettext(text)} {private local
|
|
}
|
|
|
|
decl {int g_language = 0;} {
|
|
comment {Current languages are:
|
|
0 = English
|
|
1 = German} private global
|
|
}
|
|
|
|
decl {const char *project = "fltk.org";} {private local
|
|
}
|
|
|
|
decl {const char *application = "test/preferences";} {private local
|
|
}
|
|
|
|
Function {gettext(const char *text)} {
|
|
comment {This is a minimal implementation of the GNU gettext API
|
|
for systems that don't have GNU libintl library.} open return_type {const char*}
|
|
} {
|
|
code {static const char* translation_table[][2] = {
|
|
{ "Alarm at:", "Wecken um:" },
|
|
{ "Bread:", "Brot:" },
|
|
{ "Breakfast:", "Frühstück:" },
|
|
{ "Cancel", "Abbrechen" },
|
|
{ "Drink:", "Getränk:" },
|
|
{ "English", "Englisch" },
|
|
{ "German", "Deutsch" },
|
|
{ "Get Up:", "Aufstehen:" },
|
|
{ "Language:", "Sprache:" },
|
|
{ "My Preferences", "Meine Vorlieben" },
|
|
{ "NY Times", "Der Spiegel" },
|
|
{ "Newspaper:", "Tageszeitung:" },
|
|
{ "OK", "OK" },
|
|
{ "Please restart the app to use your new language setting.",
|
|
"Bitte starten Sie die App erneut um Ihre Spracheinstellung zu nutzen." },
|
|
{ "Wear:", "Schuhwerk:" },
|
|
{ "a.m.", "früh" },
|
|
{ "bare foot", "barfuß" },
|
|
{ "brush teeth", "Zähne putzen" },
|
|
{ "coffee", "Kaffee" },
|
|
{ "eggs", "Eier" },
|
|
{ "flip flops", "Schlappen" },
|
|
{ "juice", "Saft" },
|
|
{ "left side", "linke Seite" },
|
|
{ "min.", "Min." },
|
|
{ "of the bed", "vom Bett" },
|
|
{ "p.m.", "spät" },
|
|
{ "right side", "rechte Seite" },
|
|
{ "rye", "Roggen" },
|
|
{ "sandals", "Sandalen" },
|
|
{ "shave", "rasieren" },
|
|
{ "shoes", "Schuhe" },
|
|
{ "shower", "duschen" },
|
|
{ "sourdough", "Sauerteig" },
|
|
{ "tea", "Tee" },
|
|
{ "wheat", "Weizen" },
|
|
{ "white", "Weißbrot" },
|
|
{ "with butter", "mit Butter" },
|
|
{ "with milk", "mit Milch" },
|
|
};
|
|
int lang = g_language;
|
|
int i, n = 38;
|
|
const char *found = 0L;
|
|
|
|
// As this is just a minimal demo, I did not implement binary search.
|
|
for (i=0; i<n; i++) {
|
|
if (strcmp(text, translation_table[i][0])==0) {
|
|
found = translation_table[i][lang];
|
|
break;
|
|
}
|
|
}
|
|
if (found)
|
|
return found;
|
|
else
|
|
return text;} {}
|
|
}
|
|
|
|
Function {closeWindowCB( Fl_Widget*, void* )} {open private return_type void
|
|
} {
|
|
code {Fl::delete_widget(myWindow);} {}
|
|
}
|
|
|
|
Function {saveAndCloseWindowCB( Fl_Widget*, void* )} {open private return_type void
|
|
} {
|
|
code {writePrefs();
|
|
Fl::delete_widget(myWindow);} {}
|
|
}
|
|
|
|
Function {} {open return_type int
|
|
} {
|
|
code {readLanguagePrefs();} {}
|
|
Fl_Window myWindow {
|
|
label {My Preferences}
|
|
callback closeWindowCB open
|
|
xywh {480 345 322 355} type Double visible
|
|
} {
|
|
Fl_Button {} {
|
|
label Cancel
|
|
callback closeWindowCB selected
|
|
xywh {118 316 90 24}
|
|
}
|
|
Fl_Button {} {
|
|
label OK
|
|
callback saveAndCloseWindowCB
|
|
xywh {217 316 90 24}
|
|
}
|
|
Fl_Group {} {
|
|
label {Get Up:} open
|
|
xywh {15 22 144 248} box ENGRAVED_FRAME align 5
|
|
} {
|
|
Fl_Input wAlarm {
|
|
label {Alarm at:}
|
|
xywh {25 47 60 20} align 5
|
|
}
|
|
Fl_Choice wAmPm {open
|
|
xywh {85 47 60 20} down_box BORDER_BOX
|
|
} {
|
|
MenuItem {} {
|
|
label {a.m.}
|
|
xywh {0 0 100 20}
|
|
}
|
|
MenuItem {} {
|
|
label {p.m.}
|
|
xywh {0 0 100 20}
|
|
}
|
|
}
|
|
Fl_Choice wWear {
|
|
label {Wear:} open
|
|
xywh {25 92 120 20} down_box BORDER_BOX align 5
|
|
} {
|
|
MenuItem {} {
|
|
label shoes
|
|
xywh {0 0 100 20}
|
|
}
|
|
MenuItem {} {
|
|
label sandals
|
|
xywh {0 0 100 20}
|
|
}
|
|
MenuItem {} {
|
|
label {flip flops}
|
|
xywh {0 0 100 20}
|
|
}
|
|
MenuItem {} {
|
|
label {bare foot}
|
|
xywh {0 0 100 20}
|
|
}
|
|
}
|
|
Fl_Group {} {open
|
|
xywh {25 112 120 76}
|
|
} {
|
|
Fl_Round_Button wLeft {
|
|
label {left side}
|
|
xywh {35 112 100 24} type Radio down_box ROUND_DOWN_BOX
|
|
}
|
|
Fl_Round_Button wRight {
|
|
label {right side}
|
|
xywh {35 136 100 24} type Radio down_box ROUND_DOWN_BOX
|
|
}
|
|
Fl_Box {} {
|
|
label {of the bed}
|
|
xywh {35 160 100 24}
|
|
}
|
|
}
|
|
Fl_Check_Button wShower {
|
|
label shower
|
|
xywh {25 188 105 24} down_box DOWN_BOX
|
|
}
|
|
Fl_Check_Button wShave {
|
|
label shave
|
|
xywh {25 212 105 24} down_box DOWN_BOX
|
|
}
|
|
Fl_Check_Button wBrush {
|
|
label {brush teeth}
|
|
xywh {25 236 105 24} down_box DOWN_BOX
|
|
}
|
|
}
|
|
Fl_Group {} {
|
|
label {Breakfast:} open
|
|
xywh {163 22 144 248} box ENGRAVED_FRAME align 5
|
|
} {
|
|
Fl_Choice wDrink {
|
|
label {Drink:} open
|
|
xywh {173 48 120 20} down_box BORDER_BOX align 5
|
|
} {
|
|
MenuItem {} {
|
|
label coffee
|
|
xywh {10 10 100 20}
|
|
}
|
|
MenuItem {} {
|
|
label tea
|
|
xywh {10 10 100 20}
|
|
}
|
|
MenuItem {} {
|
|
label juice
|
|
xywh {10 10 100 20}
|
|
}
|
|
}
|
|
Fl_Check_Button wMilk {
|
|
label {with milk}
|
|
xywh {173 68 100 24} down_box DOWN_BOX
|
|
}
|
|
Fl_Choice wBread {
|
|
label {Bread:} open
|
|
xywh {173 116 120 20} down_box BORDER_BOX align 5
|
|
} {
|
|
MenuItem flWheatItem {
|
|
label wheat
|
|
xywh {0 0 100 20}
|
|
}
|
|
MenuItem {} {
|
|
label white
|
|
xywh {0 0 100 20}
|
|
}
|
|
MenuItem {} {
|
|
label rye
|
|
xywh {0 0 100 20}
|
|
}
|
|
MenuItem {} {
|
|
label sourdough
|
|
xywh {0 0 100 20}
|
|
}
|
|
}
|
|
Fl_Check_Button wButter {
|
|
label {with butter}
|
|
xywh {173 136 100 24} down_box DOWN_BOX
|
|
}
|
|
Fl_Input wEggs {
|
|
label eggs
|
|
xywh {173 168 30 20} type Int align 8
|
|
}
|
|
Fl_Value_Slider wMinutes {
|
|
label {min.}
|
|
xywh {173 196 70 20} type Horizontal align 8 minimum 2 maximum 6 value 3.1
|
|
}
|
|
Fl_Input wPaper {
|
|
label {Newspaper:}
|
|
xywh {173 239 120 20} align 5
|
|
}
|
|
}
|
|
Fl_Choice wLanguage {
|
|
label {Language:}
|
|
callback {fl_message("%s", _("Please restart the app to use your new language setting."));} open
|
|
xywh {185 283 105 20} down_box BORDER_BOX
|
|
code0 {\#include <FL/fl_ask.H>}
|
|
} {
|
|
MenuItem {} {
|
|
label English
|
|
xywh {20 20 100 20}
|
|
}
|
|
MenuItem {} {
|
|
label German
|
|
xywh {20 20 100 20}
|
|
}
|
|
}
|
|
}
|
|
code {readPrefs();} {}
|
|
}
|
|
|
|
Function {readLanguagePrefs()} {
|
|
comment {Read the language setting before we create the UI.} open return_type void
|
|
} {
|
|
code {Fl_Preferences app( Fl_Preferences::USER_L, project, application );
|
|
app.get( "language", g_language, 0 );} {}
|
|
}
|
|
|
|
Function {readPrefs()} {open return_type void
|
|
} {
|
|
code {int boolValue;
|
|
int intValue;
|
|
char buffer[80];
|
|
double doubleValue;
|
|
|
|
char path[ FL_PATH_MAX ];
|
|
Fl_Preferences::Root root =
|
|
Fl_Preferences::filename(path, FL_PATH_MAX, Fl_Preferences::USER_L, project, application);
|
|
if (root == Fl_Preferences::UNKNOWN_ROOT_TYPE) {
|
|
printf("Location of future Preferences file not found.\\n");
|
|
} else {
|
|
printf("Preferences file will be located at:\\n%s\\n", path);
|
|
}
|
|
|
|
Fl_Preferences app( Fl_Preferences::USER_L, project, application );
|
|
|
|
root = app.filename(path, FL_PATH_MAX);
|
|
if (root == Fl_Preferences::UNKNOWN_ROOT_TYPE) {
|
|
printf("Location of app Preferences file not found.\\n");
|
|
} else if (root == Fl_Preferences::MEMORY) {
|
|
printf("App Preferences are memory mapped.\\n");
|
|
} else {
|
|
printf("App Preferences file is actually located at:\\n%s\\n", path);
|
|
}
|
|
|
|
app.getUserdataPath( path, sizeof(path) );
|
|
if (path[0]) {
|
|
printf("Preferences user data directory is located at:\\n%s\\n", path);
|
|
} else {
|
|
printf("Location of Preferences user data directory not found.\\n");
|
|
}
|
|
|
|
wLanguage->value( g_language );
|
|
|
|
Fl_Preferences bed( app, "Bed" );
|
|
bed.get( "alarm", buffer, "8:00", 79 );
|
|
wAlarm->value( buffer );
|
|
|
|
bed.get( "ampm", intValue, 0 );
|
|
wAmPm->value( intValue );
|
|
|
|
bed.get( "wear", intValue, 1 );
|
|
wWear->value( intValue );
|
|
|
|
int side;
|
|
bed.get( "side", side, 2 );
|
|
if ( side == 1 ) wLeft->value( 1 );
|
|
if ( side == 2 ) wRight->value( 1 );
|
|
|
|
int tasks;
|
|
bed.get( "taskFlags", tasks, 0x05 );
|
|
if ( tasks & 0x01 ) wShower->value( 1 );
|
|
if ( tasks & 0x02 ) wShave->value( 1 );
|
|
if ( tasks & 0x04 ) wBrush->value( 1 );
|
|
|
|
Fl_Preferences eat( app, "Breakfast" );
|
|
|
|
eat.get( "drink", intValue, 1 );
|
|
wDrink->value( intValue );
|
|
|
|
eat.get( "wMilk", boolValue, 0 );
|
|
wMilk->value( boolValue );
|
|
|
|
eat.get( "bread", intValue, 0 );
|
|
wBread->value( intValue );
|
|
|
|
eat.get( "wButter", boolValue, 1 );
|
|
wButter->value( boolValue );
|
|
|
|
eat.get( "nEggs", intValue, 2 );
|
|
sprintf( buffer, "%d", intValue );
|
|
wEggs->value( buffer );
|
|
|
|
eat.get( "minutes", doubleValue, 3.2 );
|
|
wMinutes->value( doubleValue );
|
|
|
|
char *flexBuffer;
|
|
eat.get( "newspaper", flexBuffer, gettext("NY Times") );
|
|
wPaper->value( flexBuffer );
|
|
if ( flexBuffer ) free( flexBuffer );
|
|
|
|
eat.get( "foo", buffer, "bar", 80 );
|
|
|
|
/** sample code only:
|
|
Fl_Preferences prev( app, "PreviousStarts" );
|
|
{
|
|
int i, n;
|
|
prev.get( "n", n, 0 );
|
|
for ( i=0; i<n; i++ )
|
|
prev.get( Fl_Preferences::Name( i ), flexBuffer, "" );
|
|
}
|
|
|
|
unsigned int hex;
|
|
eat.get( "binFoo", (void*)&hex, 0, 0, sizeof( unsigned int ) );
|
|
void *data;
|
|
eat.get( "binFoo2", data, 0, 0 );
|
|
**/} {}
|
|
}
|
|
|
|
Function {writePrefs()} {open return_type void
|
|
} {
|
|
code {Fl_Preferences app( Fl_Preferences::USER_L, project, application );
|
|
|
|
app.set( "language", wLanguage->value() );
|
|
|
|
Fl_Preferences bed( app, "Bed" );
|
|
|
|
bed.set( "alarm", wAlarm->value() );
|
|
bed.set( "ampm", wAmPm->value() );
|
|
|
|
bed.set( "wear", wWear->value() );
|
|
|
|
int side = 0;
|
|
if ( wLeft->value() ) side = 1;
|
|
if ( wRight->value() ) side = 2;
|
|
bed.set( "side", side );
|
|
|
|
int tasks = 0;
|
|
if ( wShower->value() ) tasks |= 0x01;
|
|
if ( wShave->value() ) tasks |= 0x02;
|
|
if ( wBrush->value() ) tasks |= 0x04;
|
|
bed.set( "taskFlags", tasks );
|
|
|
|
Fl_Preferences eat( app, "Breakfast" );
|
|
|
|
eat.set( "drink", wDrink->value() );
|
|
eat.set( "wMilk", wMilk->value() );
|
|
eat.set( "bread", wBread->value() );
|
|
eat.set( "wButter", wButter->value() );
|
|
|
|
eat.set( "nEggs", wEggs->value() );
|
|
eat.set( "minutes", wMinutes->value() );
|
|
|
|
eat.set( "newspaper", wPaper->value() );
|
|
|
|
eat.set( "foo", "bar\\nfly\\rBackslash: \\\\ and bell: \\007 and delete: \\177\\n" );
|
|
|
|
eat.set( Fl_Preferences::Name( 3 ), "Test3" );
|
|
|
|
/* sample: create a sub-sub-group */
|
|
Fl_Preferences eatMore( eat, "More" );
|
|
|
|
eatMore.set( "more", "stuff" );
|
|
|
|
/* all the following searches should return 1 */
|
|
int sum = 0;
|
|
sum += app.groupExists( "Breakfast" ); /* find 'eat' relative to 'app' */
|
|
sum += app.groupExists( "Breakfast/More" ); /* find 'eat.eatMore' relative to 'app' */
|
|
sum += app.groupExists( "./Breakfast/More" ); /* find 'eat.eatMore' relative to Preferences */
|
|
sum += eat.groupExists( "More" ); /* find 'eatMore' relative to 'eat' */
|
|
sum += eat.groupExists( "./Breakfast/More" ); /* find 'eat.eatMore' relative to Preferences */
|
|
sum += eat.groupExists( "." ); /* find myself ('eat') */
|
|
sum += eat.groupExists( "./" ); /* find the topmost group ('app') */
|
|
if ( sum != 7 )
|
|
fl_message( "Assertion failed:\\nNot all group entries were found!" );
|
|
|
|
/* sample code only: */
|
|
// unsigned int hex = 0xefbeadde;
|
|
// unsigned int size_of_bed = sizeof( bed ); // size of Fl_Preferences 'bed'
|
|
// eat.set( "binFoo", (void*)&hex, sizeof( unsigned int ) );
|
|
// eat.set( "SizeOfBed", (int)size_of_bed );
|
|
// eat.set( "Prefs_Bed", (void*)&bed, sizeof( bed ) );} {selected
|
|
}
|
|
}
|