Fluid Fl_Widget::image() path fixes. (#536)

* Adding strings and design file to source view panel

* Fluid: Fixed source dir recursion, fixed relative image reading path.

* Renaming source_dir to designfile_dir in some functions.
This commit is contained in:
Matthias Melcher
2022-11-09 23:12:55 +01:00
committed by GitHub
parent f41861976b
commit 56cba05672
10 changed files with 215 additions and 76 deletions
+15 -1
View File
@@ -2,7 +2,7 @@
// Code editor widget for the Fast Light Tool Kit (FLTK).
// Syntax highlighting rewritten by erco@seriss.com 09/15/20.
//
// Copyright 1998-2021 by Bill Spitzak and others.
// Copyright 1998-2022 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -294,3 +294,17 @@ void CodeViewer::draw()
CodeEditor::draw();
Fl::set_color(FL_SELECTION_COLOR, c);
}
// ---- DesignViewer implementation
/**
Create a DesignViewer widget.
\param[in] X, Y, W, H position and size of the widget
\param[in] L optional label
*/
DesignViewer::DesignViewer(int X, int Y, int W, int H, const char *L)
: Fl_Text_Display(X, Y, W, H, L)
{
buffer(new Fl_Text_Buffer);
}
+9 -1
View File
@@ -2,7 +2,7 @@
// Code editor widget for the Fast Light Tool Kit (FLTK).
// Syntax highlighting rewritten by erco@seriss.com 09/15/20.
//
// Copyright 1998-2021 by Bill Spitzak and others.
// Copyright 1998-2022 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -66,4 +66,12 @@ protected:
void draw();
};
// ---- DesignViewer declaration
class DesignViewer : public Fl_Text_Display {
public:
DesignViewer(int X, int Y, int W, int H, const char *L=0);
int top_line() { return get_absolute_top_line_number(); }
};
#endif // !CodeEditor_h
+4 -4
View File
@@ -1128,9 +1128,9 @@ void Fl_Data_Type::open() {
if (w == data_panel_cancel) goto BREAK2;
else if (w == data_panel_ok) break;
else if (w == data_filebrowser) {
goto_source_dir();
goto_designfile_dir();
const char *fn = fl_file_chooser("Load Inline Data", 0L, data_filename->value(), 1);
leave_source_dir();
leave_designfile_dir();
if (fn) {
if (strcmp(fn, data_filename->value()))
set_modflag(1);
@@ -1217,9 +1217,9 @@ void Fl_Data_Type::write_code1() {
int nData = -1;
// path should be set correctly already
if (filename_ && !write_sourceview) {
goto_source_dir();
goto_designfile_dir();
FILE *f = fl_fopen(filename_, "rb");
leave_source_dir();
leave_designfile_dir();
if (!f) {
message = "Can't include data from file. Can't open";
} else {
+18 -7
View File
@@ -104,9 +104,11 @@ void Fluid_Image::write_static() {
}
write_c("static const unsigned char %s[] =\n", idata_name);
goto_designfile_dir();
FILE *f = fl_fopen(name(), "rb");
leave_designfile_dir();
if (!f) {
// message = "Can't inline file into source code. Can't open";
write_file_error("JPEG");
} else {
fseek(f, 0, SEEK_END);
size_t nData = ftell(f);
@@ -131,9 +133,11 @@ void Fluid_Image::write_static() {
}
write_c("static const char %s[] =\n", idata_name);
goto_designfile_dir();
FILE *f = fl_fopen(name(), "rb");
leave_designfile_dir();
if (!f) {
// message = "Can't inline file into source code. Can't open";
write_file_error("SVG");
} else {
fseek(f, 0, SEEK_END);
size_t nData = ftell(f);
@@ -164,6 +168,13 @@ void Fluid_Image::write_static() {
}
}
void Fluid_Image::write_file_error(const char *fmt) {
write_c("#warning Cannot read %s file \"%s\": %s\n", fmt, name(), strerror(errno));
goto_designfile_dir();
write_c("// Searching in path \"%s\"\n", fl_getcwd(0, FL_PATH_MAX));
leave_designfile_dir();
}
void Fluid_Image::write_initializer(const char *type_name, const char *format, ...) {
/* Outputs code that returns (and initializes if needed) an Fl_Image as follows:
static Fl_Image *'function_name_'() {
@@ -213,11 +224,11 @@ Fluid_Image* Fluid_Image::find(const char *iname) {
// no, so now see if the file exists:
goto_source_dir();
goto_designfile_dir();
FILE *f = fl_fopen(iname,"rb");
if (!f) {
read_error("%s : %s",iname,strerror(errno));
leave_source_dir();
leave_designfile_dir();
return 0;
}
fclose(f);
@@ -229,7 +240,7 @@ Fluid_Image* Fluid_Image::find(const char *iname) {
ret = 0;
read_error("%s : unrecognized image format", iname);
}
leave_source_dir();
leave_designfile_dir();
if (!ret) return 0;
// make a new entry in the table:
@@ -278,12 +289,12 @@ Fluid_Image::~Fluid_Image() {
const char *ui_find_image_name;
Fluid_Image *ui_find_image(const char *oldname) {
goto_source_dir();
goto_designfile_dir();
fl_file_chooser_ok_label("Use Image");
const char *name = fl_file_chooser("Image?","Image Files (*.{bm,bmp,gif,jpg,pbm,pgm,png,ppm,xbm,xpm,svg})",oldname,1);
fl_file_chooser_ok_label(NULL);
ui_find_image_name = name;
Fluid_Image *ret = (name && *name) ? Fluid_Image::find(name) : 0;
leave_source_dir();
leave_designfile_dir();
return ret;
}
+1
View File
@@ -42,6 +42,7 @@ public:
void write_initializer(const char *type_name, const char *format, ...);
void write_code(const char *var, int inactive = 0);
void write_inline(int inactive = 0);
void write_file_error(const char *fmt);
const char *name() const {return name_;}
};
+84 -51
View File
@@ -1,7 +1,7 @@
//
// FLUID main entry for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2021 by Bill Spitzak and others.
// Copyright 1998-2022 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -145,11 +145,11 @@ int modflag_c = 0;
/// Application work directory, stored here when temporarily changing to the source code directory.
/// \see goto_source_dir()
static char* pwd = NULL;
static char* app_work_dir = NULL;
/// Set, if the current working directory is in the source code folder vs. the app working space.
/// \see goto_source_dir()
static char in_source_dir = 0;
static char in_designfile_dir = 0;
/// Set, if Fluid was started with the command line argument -u
int update_file = 0; // fluid -u
@@ -253,35 +253,43 @@ void update_sourceview_timer(void*);
Remember the the previous directory, so \c leave_source_dir() can return there.
\see leave_source_dir(), pwd, in_source_dir
*/
void goto_source_dir() {
if (in_source_dir) return;
void goto_designfile_dir() {
in_designfile_dir++;
if (in_designfile_dir>1) return;
if (!filename || !*filename) return;
const char *p = fl_filename_name(filename);
if (p <= filename) return; // it is in the current directory
char buffer[FL_PATH_MAX];
strlcpy(buffer, filename, sizeof(buffer));
int n = (int)(p-filename); if (n>1) n--; buffer[n] = 0;
if (!pwd) {
pwd = fl_getcwd(0, FL_PATH_MAX);
if (!pwd) {fprintf(stderr, "getwd : %s\n",strerror(errno)); return;}
int n = (int)(p-filename);
if (n>1) n--;
buffer[n] = 0;
if (!app_work_dir) {
app_work_dir = fl_getcwd(0, FL_PATH_MAX);
if (!app_work_dir) {
fprintf(stderr, "goto_source_dir: getwd: %s\n", strerror(errno));
return;
}
}
if (fl_chdir(buffer) < 0) {
fprintf(stderr, "Can't chdir to %s : %s\n", buffer, strerror(errno));
if (buffer[0] && (fl_chdir(buffer) < 0)) {
fprintf(stderr, "goto_source_dir: can't chdir to %s: %s\n", buffer, strerror(errno));
return;
}
in_source_dir = 1;
// fprintf(stderr, "chdir to %s\n", fl_getcwd(0, FL_PATH_MAX));
}
/**
Change the current working directory to its previous directory.
\see goto_source_dir(), pwd, in_source_dir
*/
void leave_source_dir() {
if (!in_source_dir) return;
if (fl_chdir(pwd) < 0) {
fprintf(stderr, "Can't chdir to %s : %s\n", pwd, strerror(errno));
void leave_designfile_dir() {
if (in_designfile_dir == 0) return; // error: called leave_... more often the goto_...
in_designfile_dir--;
if (in_designfile_dir) return;
if (fl_chdir(app_work_dir) < 0) {
fprintf(stderr, "Can't chdir to %s : %s\n", app_work_dir, strerror(errno));
}
in_source_dir = 0;
// fprintf(stderr, "chdir back to %s\n", app_work_dir);
}
/**
@@ -918,9 +926,9 @@ int write_code_files() {
} else {
strlcpy(hname, header_file_name, sizeof(hname));
}
if (!batch_mode) goto_source_dir();
if (!batch_mode) goto_designfile_dir();
int x = write_code(cname,hname);
if (!batch_mode) leave_source_dir();
if (!batch_mode) leave_designfile_dir();
strlcat(cname, " and ", sizeof(cname));
strlcat(cname, hname, sizeof(cname));
if (batch_mode) {
@@ -957,9 +965,9 @@ void write_strings_cb(Fl_Widget *, void *) {
char sname[FL_PATH_MAX];
strlcpy(sname, fl_filename_name(filename), sizeof(sname));
fl_filename_setext(sname, sizeof(sname), exts[i18n_type]);
if (!batch_mode) goto_source_dir();
if (!batch_mode) goto_designfile_dir();
int x = write_strings(sname);
if (!batch_mode) leave_source_dir();
if (!batch_mode) leave_designfile_dir();
if (batch_mode) {
if (x) {fprintf(stderr,"%s : %s\n",sname,strerror(errno)); exit(1);}
} else {
@@ -1615,7 +1623,7 @@ void set_filename(const char *c) {
/**
Set the "modified" flag and update the title of the main window.
The first argument sets the modifaction state of the current design against
The first argument sets the modification state of the current design against
the corresponding .fl design file. Any change to the widget tree will mark
the design 'modified'. Saving the design will mark it clean.
@@ -1684,6 +1692,7 @@ void set_modflag(int mf, int mfc) {
static char *sv_source_filename = NULL;
static char *sv_header_filename = NULL;
static char *sv_design_filename = NULL;
/**
Update the header and source code highlighting depending on the
@@ -1732,18 +1741,21 @@ void update_sourceview_position()
*/
void update_sourceview_position_cb(Fl_Tabs*, void*)
{
// make sure that the selected tab shows the current view
update_sourceview_cb(0,0);
// highlight the selected widget in the selected tab
update_sourceview_position();
}
/**
Generate a header and source file in a temporary directory and
load those into the Code Viewer widgets.
Generate a header, source, strings, or design file in a temporary directory
and load those into the Code Viewer widgets.
*/
void update_sourceview_cb(Fl_Button*, void*)
{
if (!sourceview_panel || !sourceview_panel->visible())
return;
// generate space for the source and header file filenames
if (!sv_source_filename) {
sv_source_filename = (char*)malloc(FL_PATH_MAX);
fluid_prefs.getUserdataPath(sv_source_filename, FL_PATH_MAX);
@@ -1754,34 +1766,55 @@ void update_sourceview_cb(Fl_Button*, void*)
fluid_prefs.getUserdataPath(sv_header_filename, FL_PATH_MAX);
strlcat(sv_header_filename, "source_view_tmp.h", FL_PATH_MAX);
}
strlcpy(i18n_program, fl_filename_name(sv_source_filename), sizeof(i18n_program));
fl_filename_setext(i18n_program, sizeof(i18n_program), "");
const char *code_file_name_bak = code_file_name;
code_file_name = sv_source_filename;
const char *header_file_name_bak = header_file_name;
header_file_name = sv_header_filename;
// generate the code and load the files
write_sourceview = 1;
// generate files
if (write_code(sv_source_filename, sv_header_filename))
{
// load file into source editor
int pos = sv_source->top_line();
sv_source->buffer()->loadfile(sv_source_filename);
sv_source->scroll(pos, 0);
// load file into header editor
pos = sv_header->top_line();
sv_header->buffer()->loadfile(sv_header_filename);
sv_header->scroll(pos, 0);
// update the source code highlighting
update_sourceview_position();
if (!sv_design_filename) {
sv_design_filename = (char*)malloc(FL_PATH_MAX);
fluid_prefs.getUserdataPath(sv_design_filename, FL_PATH_MAX);
strlcat(sv_design_filename, "source_view_tmp.fl", FL_PATH_MAX);
}
write_sourceview = 0;
code_file_name = code_file_name_bak;
header_file_name = header_file_name_bak;
if (sv_design->visible_r()) {
write_file(sv_design_filename);
int top = sv_design->top_line();
sv_design->buffer()->loadfile(sv_design_filename);
sv_design->scroll(top, 0);
} else if (sv_strings->visible_r()) {
static const char *exts[] = { ".txt", ".po", ".msg" };
char fn[FL_PATH_MAX];
fluid_prefs.getUserdataPath(fn, FL_PATH_MAX);
fl_filename_setext(fn, FL_PATH_MAX, exts[i18n_type]);
write_strings(fn);
int top = sv_strings->top_line();
sv_strings->buffer()->loadfile(fn);
sv_strings->scroll(top, 0);
} else if (sv_source->visible_r() || sv_header->visible_r()) {
strlcpy(i18n_program, fl_filename_name(sv_source_filename), sizeof(i18n_program));
fl_filename_setext(i18n_program, sizeof(i18n_program), "");
const char *code_file_name_bak = code_file_name;
code_file_name = sv_source_filename;
const char *header_file_name_bak = header_file_name;
header_file_name = sv_header_filename;
// generate the code and load the files
write_sourceview = 1;
// generate files
if (write_code(sv_source_filename, sv_header_filename))
{
// load file into source editor
int pos = sv_source->top_line();
sv_source->buffer()->loadfile(sv_source_filename);
sv_source->scroll(pos, 0);
// load file into header editor
pos = sv_header->top_line();
sv_header->buffer()->loadfile(sv_header_filename);
sv_header->scroll(pos, 0);
// update the source code highlighting
update_sourceview_position();
}
write_sourceview = 0;
code_file_name = code_file_name_bak;
header_file_name = header_file_name_bak;
}
}
/**
+2 -2
View File
@@ -67,8 +67,8 @@ extern Fl_Menu_Item *overlay_item;
extern int modflag;
extern void goto_source_dir();
extern void leave_source_dir();
extern void goto_designfile_dir();
extern void leave_designfile_dir();
extern int update_file; // fluid -u
extern int compile_file; // fluid -c
+46
View File
@@ -1484,6 +1484,10 @@ CodeViewer *sv_source=(CodeViewer *)0;
CodeViewer *sv_header=(CodeViewer *)0;
DesignViewer *sv_strings=(DesignViewer *)0;
DesignViewer *sv_design=(DesignViewer *)0;
Fl_Light_Button *sv_autorefresh=(Fl_Light_Button *)0;
Fl_Light_Button *sv_autoposition=(Fl_Light_Button *)0;
@@ -1538,6 +1542,48 @@ Fl_Double_Window* make_sourceview() {
} // CodeViewer* sv_header
o->end();
} // Fl_Group* o
{ Fl_Group* o = new Fl_Group(10, 35, 500, 415, "Strings");
o->labelsize(13);
o->hide();
{ DesignViewer* o = sv_strings = new DesignViewer(20, 50, 480, 390);
sv_strings->box(FL_DOWN_FRAME);
sv_strings->color(FL_BACKGROUND2_COLOR);
sv_strings->selection_color(FL_SELECTION_COLOR);
sv_strings->labeltype(FL_NORMAL_LABEL);
sv_strings->labelfont(0);
sv_strings->labelsize(14);
sv_strings->labelcolor(FL_FOREGROUND_COLOR);
sv_strings->textfont(4);
sv_strings->textsize(11);
sv_strings->align(Fl_Align(FL_ALIGN_TOP));
sv_strings->when(FL_WHEN_RELEASE);
Fl_Group::current()->resizable(sv_strings);
o->linenumber_width(60);
o->linenumber_size(o->Fl_Text_Display::textsize());
} // DesignViewer* sv_strings
o->end();
} // Fl_Group* o
{ Fl_Group* o = new Fl_Group(10, 35, 500, 415, "Design");
o->labelsize(13);
o->hide();
{ DesignViewer* o = sv_design = new DesignViewer(20, 50, 480, 390);
sv_design->box(FL_DOWN_FRAME);
sv_design->color(FL_BACKGROUND2_COLOR);
sv_design->selection_color(FL_SELECTION_COLOR);
sv_design->labeltype(FL_NORMAL_LABEL);
sv_design->labelfont(0);
sv_design->labelsize(14);
sv_design->labelcolor(FL_FOREGROUND_COLOR);
sv_design->textfont(4);
sv_design->textsize(11);
sv_design->align(Fl_Align(FL_ALIGN_TOP));
sv_design->when(FL_WHEN_RELEASE);
Fl_Group::current()->resizable(sv_design);
o->linenumber_width(60);
o->linenumber_size(o->Fl_Text_Display::textsize());
} // DesignViewer* sv_design
o->end();
} // Fl_Group* o
sv_tab->end();
Fl_Group::current()->resizable(sv_tab);
} // Fl_Tabs* sv_tab
+34 -10
View File
@@ -476,9 +476,10 @@ Function {make_class_panel()} {open
}
}
Function {make_comment_panel()} {} {
Function {make_comment_panel()} {open
} {
Fl_Window comment_panel {
label {Comment Properties} open
label {Comment Properties}
xywh {780 296 550 280} type Double labelsize 11 hide resizable
code0 {o->size_range(320, 180);} modal
} {
@@ -528,7 +529,7 @@ Function {make_comment_panel()} {} {
}
}
Function {type_make_cb(Fl_Widget*,void*d)} {open return_type void
Function {type_make_cb(Fl_Widget*,void*d)} {return_type void
} {
code {const char *type_name = (const char*)d;
if (Fl_Type::current && Fl_Type::current->is_group())
@@ -544,7 +545,7 @@ Function {make_widgetbin()} {open
callback {if (Fl::event()==FL_SHORTCUT && Fl::event_key()==FL_Escape)
exit_cb((Fl_Widget*)o, v);
else
toggle_widgetbin_cb((Fl_Widget*)o, v);} open
toggle_widgetbin_cb((Fl_Widget*)o, v);}
xywh {449 206 600 102} type Single align 80 non_modal visible
} {
Fl_Group {} {
@@ -647,7 +648,7 @@ else
}
Fl_Button {} {
user_data {"Fl_Flex"}
callback type_make_cb selected
callback type_make_cb
tooltip Flex xywh {139 46 24 24} box THIN_UP_BOX
code0 {o->image(pixmap[56]);}
class Widget_Bin_Button
@@ -973,18 +974,19 @@ else
}
}
Function {make_sourceview()} {} {
Function {make_sourceview()} {open
} {
Fl_Window sourceview_panel {
label {Code View}
callback toggle_sourceview_cb
xywh {430 273 520 490} type Double align 80 hide resizable size_range {384 120 0 0}
callback toggle_sourceview_cb open
xywh {464 265 520 490} type Double align 80 resizable size_range {384 120 0 0} visible
} {
Fl_Tabs sv_tab {
callback update_sourceview_position_cb
callback update_sourceview_position_cb open
xywh {10 10 500 440} selection_color 4 labelcolor 7 resizable
} {
Fl_Group {} {
label Source open
label Source open selected
xywh {10 35 500 415} labelsize 13 resizable
} {
Fl_Text_Editor sv_source {
@@ -1007,6 +1009,28 @@ Function {make_sourceview()} {} {
class CodeViewer
}
}
Fl_Group {} {
label Strings open
xywh {10 35 500 415} labelsize 13 hide
} {
Fl_Text_Display sv_strings {
xywh {20 50 480 390} textfont 4 textsize 11 resizable
code1 {o->linenumber_width(60);}
code2 {o->linenumber_size(o->Fl_Text_Display::textsize());}
class DesignViewer
}
}
Fl_Group {} {
label Design open
xywh {10 35 500 415} labelsize 13 hide
} {
Fl_Text_Display sv_design {
xywh {20 50 480 390} textfont 4 textsize 11 resizable
code1 {o->linenumber_width(60);}
code2 {o->linenumber_size(o->Fl_Text_Display::textsize());}
class DesignViewer
}
}
}
Fl_Group {} {
xywh {10 460 500 20}
+2
View File
@@ -114,6 +114,8 @@ extern void update_sourceview_position_cb(Fl_Tabs*, void*);
extern Fl_Tabs *sv_tab;
extern CodeViewer *sv_source;
extern CodeViewer *sv_header;
extern DesignViewer *sv_strings;
extern DesignViewer *sv_design;
extern void update_sourceview_cb(Fl_Button*, void*);
extern Fl_Light_Button *sv_autorefresh;
extern Fl_Light_Button *sv_autoposition;