diff options
| -rw-r--r-- | fluid/CodeEditor.h | 1 | ||||
| -rw-r--r-- | fluid/Fl_Type.cxx | 2 | ||||
| -rw-r--r-- | fluid/Fl_Type.h | 4 | ||||
| -rw-r--r-- | fluid/Fl_Widget_Type.cxx | 3 | ||||
| -rw-r--r-- | fluid/code.cxx | 56 | ||||
| -rw-r--r-- | fluid/fluid.cxx | 150 | ||||
| -rw-r--r-- | fluid/function_panel.cxx | 87 | ||||
| -rw-r--r-- | fluid/function_panel.fl | 67 | ||||
| -rw-r--r-- | fluid/function_panel.h | 12 |
9 files changed, 372 insertions, 10 deletions
diff --git a/fluid/CodeEditor.h b/fluid/CodeEditor.h index 4b646849b..04c51bd09 100644 --- a/fluid/CodeEditor.h +++ b/fluid/CodeEditor.h @@ -67,6 +67,7 @@ class CodeEditor : public Fl_Text_Editor { CodeEditor(int X, int Y, int W, int H, const char *L=0); ~CodeEditor(); + int top_line() { return get_absolute_top_line_number(); } }; #endif // !CodeEditor_h diff --git a/fluid/Fl_Type.cxx b/fluid/Fl_Type.cxx index 222444cd5..92e1c807c 100644 --- a/fluid/Fl_Type.cxx +++ b/fluid/Fl_Type.cxx @@ -436,6 +436,8 @@ Fl_Type::Fl_Type() { callback_ = 0; rtti = 0; level = 0; + code_line = header_line = -1; + code_line_end = header_line_end = -1; } static void fixvisible(Fl_Type *p) { diff --git a/fluid/Fl_Type.h b/fluid/Fl_Type.h index e76368c08..18f6f5303 100644 --- a/fluid/Fl_Type.h +++ b/fluid/Fl_Type.h @@ -72,6 +72,9 @@ public: // things that should not be public: Fl_Type *factory; const char *callback_name(); + int code_line, header_line; + int code_line_end, header_line_end; + public: virtual ~Fl_Type(); @@ -737,6 +740,7 @@ void write_indent(int n); void write_open(int); void write_close(int n); extern int write_number; +extern int write_sourceview; void write_public(int state); // writes pubic:/private: as needed extern int indentation; extern const char* indent(); diff --git a/fluid/Fl_Widget_Type.cxx b/fluid/Fl_Widget_Type.cxx index 19bf16926..accaa3a2a 100644 --- a/fluid/Fl_Widget_Type.cxx +++ b/fluid/Fl_Widget_Type.cxx @@ -1710,6 +1710,7 @@ Fl_Type *Fl_Type::current; extern void redraw_overlays(); extern void redraw_browser(); +extern void update_sourceview_position(); // Called when ui changes what objects are selected: // p is selected object, null for all deletions (we must throw away @@ -1742,6 +1743,8 @@ void selection_changed(Fl_Type *p) { redraw_overlays(); // load the panel with the new settings: load_panel(); + // update the source viewer to show the code for the selected object + update_sourceview_position(); } //////////////////////////////////////////////////////////////// diff --git a/fluid/code.cxx b/fluid/code.cxx index d50f37fd9..25f68fc45 100644 --- a/fluid/code.cxx +++ b/fluid/code.cxx @@ -263,13 +263,21 @@ void write_h(const char* format,...) { #include <FL/filename.H> int write_number; +int write_sourceview; // recursively dump code, putting children between the two parts // of the parent code: static Fl_Type* write_code(Fl_Type* p) { - // don't write the last comment until the very end + if (write_sourceview) { + p->code_line = (int)ftell(code_file); + if (p->header_line_end==-1) + p->header_line = (int)ftell(header_file); + } + // write all code that come before the children code + // (but don't write the last comment until the very end) if (!(p==Fl_Type::last && p->is_comment())) p->write_code1(); + // recursively write the code of all children Fl_Type* q; if (p->is_widget() && p->is_class()) { // Handle widget classes specially @@ -283,6 +291,7 @@ static Fl_Type* write_code(Fl_Type* p) { } } + // write all code that come after the children p->write_code2(); for (q = p->next; q && q->level > p->level;) { @@ -298,27 +307,35 @@ static Fl_Type* write_code(Fl_Type* p) { write_h("};\n"); } else { for (q = p->next; q && q->level > p->level;) q = write_code(q); - + // write all code that come after the children p->write_code2(); } + if (write_sourceview) { + p->code_line_end = (int)ftell(code_file); + if (p->header_line_end==-1) + p->header_line_end = (int)ftell(header_file); + } return q; } extern const char* header_file_name; int write_code(const char *s, const char *t) { + const char *filemode = "w"; + if (write_sourceview) + filemode = "wb"; write_number++; delete id_root; id_root = 0; indentation = 0; if (!s) code_file = stdout; else { - FILE *f = fopen(s,"w"); + FILE *f = fopen(s, filemode); if (!f) return 0; code_file = f; } if (!t) header_file = stdout; else { - FILE *f = fopen(t,"w"); + FILE *f = fopen(t, filemode); if (!f) {fclose(code_file); return 0;} header_file = f; } @@ -326,8 +343,16 @@ int write_code(const char *s, const char *t) { // a copyright notice. We print that before anything else in the file! Fl_Type* first_type = Fl_Type::first; if (first_type && first_type->is_comment()) { - // this is ok, because comments have no children or code2 blocks + if (write_sourceview) { + first_type->code_line = (int)ftell(code_file); + first_type->header_line = (int)ftell(header_file); + } + // it is ok to write non-recusive code here, because comments have no children or code2 blocks first_type->write_code1(); + if (write_sourceview) { + first_type->code_line_end = (int)ftell(code_file); + first_type->header_line_end = (int)ftell(header_file); + } first_type = first_type->next; } @@ -373,9 +398,20 @@ int write_code(const char *s, const char *t) { } for (Fl_Type* p = first_type; p;) { // write all static data for this & all children first + if (write_sourceview) p->header_line = (int)ftell(header_file); p->write_static(); - for (Fl_Type* q = p->next; q && q->level > p->level; q = q->next) + if (write_sourceview) { + p->header_line_end = (int)ftell(header_file); + if (p->header_line==p->header_line_end) p->header_line_end = -1; + } + for (Fl_Type* q = p->next; q && q->level > p->level; q = q->next) { + if (write_sourceview) q->header_line = (int)ftell(header_file); q->write_static(); + if (write_sourceview) { + q->header_line_end = (int)ftell(header_file); + if (q->header_line==q->header_line_end) q->header_line_end = -1; + } + } // then write the nested code: p = write_code(p); } @@ -388,7 +424,15 @@ int write_code(const char *s, const char *t) { Fl_Type* last_type = Fl_Type::last; if (last_type && last_type->is_comment()) { + if (write_sourceview) { + last_type->code_line = (int)ftell(code_file); + last_type->header_line = (int)ftell(header_file); + } last_type->write_code1(); + if (write_sourceview) { + last_type->code_line_end = (int)ftell(code_file); + last_type->header_line_end = (int)ftell(header_file); + } } int x = fclose(code_file); diff --git a/fluid/fluid.cxx b/fluid/fluid.cxx index 789d1bac0..cf52c3260 100644 --- a/fluid/fluid.cxx +++ b/fluid/fluid.cxx @@ -381,6 +381,14 @@ void exit_cb(Fl_Widget *,void *) { save_position(widgetbin_panel,"widgetbin_pos"); delete widgetbin_panel; } + if (sourceview_panel) { + Fl_Preferences svp(fluid_prefs, "sourceview"); + svp.set("autorefresh", sv_autorefresh->value()); + svp.set("autoposition", sv_autoposition->value()); + svp.set("tab", sv_tab->find(sv_tab->value())); + save_position(sourceview_panel,"sourceview_pos"); + delete sourceview_panel; + } if (about_panel) delete about_panel; if (help_dialog) @@ -1550,6 +1558,7 @@ void print_cb(Fl_Return_Button *, void *) { extern Fl_Menu_Item New_Menu[]; void toggle_widgetbin_cb(Fl_Widget *, void *); +void toggle_sourceview_cb(Fl_Double_Window *, void *); Fl_Menu_Item Main_Menu[] = { {"&File",0,0,0,FL_SUBMENU}, @@ -1596,7 +1605,9 @@ Fl_Menu_Item Main_Menu[] = { {"Ung&roup", FL_F+8, ungroup_cb,0, FL_MENU_DIVIDER}, {"Hide O&verlays",FL_CTRL+FL_SHIFT+'o',toggle_overlays}, #define WIDGETBIN_ITEM 41 - {"Show Widget &Bin...",FL_ALT+'b',toggle_widgetbin_cb, 0, FL_MENU_DIVIDER}, + {"Show Widget &Bin...",FL_ALT+'b',toggle_widgetbin_cb}, +#define SOURCEVIEW_ITEM 42 + {"Show Source Code...",FL_ALT+FL_SHIFT+'s', (Fl_Callback*)toggle_sourceview_cb, 0, FL_MENU_DIVIDER}, {"Pro&ject Settings...",FL_ALT+'p',show_project_cb}, {"GU&I Settings...",FL_ALT+FL_SHIFT+'p',show_settings_cb}, {0}, @@ -1688,6 +1699,37 @@ void toggle_widgetbin_cb(Fl_Widget *, void *) { } +void toggle_sourceview_cb(Fl_Double_Window *, void *) { + if (!sourceview_panel) { + make_sourceview(); + sourceview_panel->callback((Fl_Callback*)toggle_sourceview_cb); + Fl_Preferences svp(fluid_prefs, "sourceview"); + int autorefresh; + svp.get("autorefresh", autorefresh, 1); + sv_autorefresh->value(autorefresh); + int autoposition; + svp.get("autoposition", autoposition, 1); + sv_autoposition->value(autoposition); + int tab; + svp.get("tab", tab, 0); + if (tab>=0 && tab<sv_tab->children()) sv_tab->value(sv_tab->child(tab)); + if (!position_window(sourceview_panel,"sourceview_pos", 0, 320, 120, 550, 500)) return; + } + + if (sourceview_panel->visible()) { + sourceview_panel->hide(); + Main_Menu[SOURCEVIEW_ITEM].label("Show Source Code..."); + } else { + sourceview_panel->show(); + Main_Menu[SOURCEVIEW_ITEM].label("Hide Source Code..."); + update_sourceview_cb(0,0); + } +} + +void toggle_sourceview_b_cb(Fl_Button*, void *) { + toggle_sourceview_cb(0,0); +} + void make_main_window() { fluid_prefs.get("snap", snap, 1); fluid_prefs.get("gridx", gridx, 5); @@ -1933,6 +1975,102 @@ void set_filename(const char *c) { set_modflag(modflag); } +// +// The Source View system offers an immediate preview of the code +// files that will be generated by FLUID. It also marks the code +// generated for the last selected item in the header and the source +// file. +// +// Can we patent this? ;-) - Matt, mm@matthiasm.com +// + +// +// Update the header and source code highlighting depending on the +// currently selected object +// +void update_sourceview_position() +{ + if (sv_autoposition->value()==0) + return; + if (sourceview_panel && sourceview_panel->visible() && Fl_Type::current) { + int pos0, pos1; + if (sv_source->visible_r()) { + pos0 = Fl_Type::current->code_line; + pos1 = Fl_Type::current->code_line_end; + if (pos0>=0) { + if (pos1<pos0) + pos1 = pos0; + sv_source->buffer()->highlight(pos0, pos1); + int line = sv_source->buffer()->count_lines(0, pos0); + sv_source->scroll(line, 0); + } + } + if (sv_header->visible_r()) { + pos0 = Fl_Type::current->header_line; + pos1 = Fl_Type::current->header_line_end; + if (pos0>=0) { + if (pos1<pos0) + pos1 = pos0; + sv_header->buffer()->highlight(pos0, pos1); + int line = sv_header->buffer()->count_lines(0, pos0); + sv_header->scroll(line, 0); + } + } + } +} + +void update_sourceview_position_cb(Fl_Tabs*, void*) +{ + update_sourceview_position(); +} + +static char *sv_source_filename = 0; +static char *sv_header_filename = 0; + +// +// Generate a header and source file in a temporary directory and +// load those into the Code Viewer widgets. +// +void update_sourceview_cb(Fl_Button*, void*) +{ + // 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); + strlcat(sv_source_filename, "source_view_tmp.cxx", FL_PATH_MAX); + } + if (!sv_header_filename) { + sv_header_filename = (char*)malloc(FL_PATH_MAX); + fluid_prefs.getUserdataPath(sv_header_filename, FL_PATH_MAX); + strlcat(sv_header_filename, "source_view_tmp.h", FL_PATH_MAX); + } + // generate the code and load the files + if (sourceview_panel && sourceview_panel->visible()) + { + 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; + } +} + +void update_sourceview_timer(void*) +{ + update_sourceview_cb(0,0); +} + // Set the "modified" flag and update the title of the main window... void set_modflag(int mf) { const char *basename; @@ -1953,6 +2091,15 @@ void set_modflag(int mf) { main_window->label(title); } else main_window->label(basename); } + // if the UI was modified in any way, update the Source View panel + if (sourceview_panel && sourceview_panel->visible() && sv_autorefresh->value()) + { + // we will only update ealiest 0.5 seconds after the last change, and only + // if no other change was made, so dragging a widget will not generate any + // CPU load + Fl::remove_timeout(update_sourceview_timer, 0); + Fl::add_timeout(0.5, update_sourceview_timer, 0); + } // Enable/disable the Save menu item... if (modflag) Main_Menu[SAVE_ITEM].activate(); @@ -2030,6 +2177,7 @@ int main(int argc,char **argv) { position_window(main_window,"main_window_pos", 1, 10, 30, WINWIDTH, WINHEIGHT ); main_window->show(argc,argv); toggle_widgetbin_cb(0,0); + toggle_sourceview_cb(0,0); if (!c && openlast_button->value() && absolute_history[0][0]) { // Open previous file when no file specified... open_history_cb(0, absolute_history[0]); diff --git a/fluid/function_panel.cxx b/fluid/function_panel.cxx index 04c1461b1..2cc95cad1 100644 --- a/fluid/function_panel.cxx +++ b/fluid/function_panel.cxx @@ -839,6 +839,93 @@ Fl_Window* make_widgetbin() { return w; } +Fl_Double_Window *sourceview_panel=(Fl_Double_Window *)0; + +Fl_Tabs *sv_tab=(Fl_Tabs *)0; + +CodeEditor *sv_source=(CodeEditor *)0; + +CodeEditor *sv_header=(CodeEditor *)0; + +Fl_Light_Button *sv_autorefresh=(Fl_Light_Button *)0; + +Fl_Light_Button *sv_autoposition=(Fl_Light_Button *)0; + +Fl_Double_Window* make_sourceview() { + Fl_Double_Window* w; + { Fl_Double_Window* o = sourceview_panel = new Fl_Double_Window(544, 500, "Code View"); + w = o; + o->callback((Fl_Callback*)toggle_sourceview_cb); + { Fl_Tabs* o = sv_tab = new Fl_Tabs(20, 10, 500, 440); + o->callback((Fl_Callback*)update_sourceview_position_cb); + { Fl_Group* o = new Fl_Group(20, 35, 500, 415, "Source"); + o->labelsize(13); + { CodeEditor* o = sv_source = new CodeEditor(25, 40, 490, 405); + o->box(FL_DOWN_FRAME); + o->color(FL_BACKGROUND2_COLOR); + o->selection_color(FL_SELECTION_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); + o->textfont(4); + o->textsize(11); + o->align(FL_ALIGN_TOP); + o->when(FL_WHEN_RELEASE); + Fl_Group::current()->resizable(o); + } + o->end(); + Fl_Group::current()->resizable(o); + } + { Fl_Group* o = new Fl_Group(20, 35, 500, 415, "Header"); + o->labelsize(13); + o->hide(); + { CodeEditor* o = sv_header = new CodeEditor(25, 40, 490, 405); + o->box(FL_DOWN_FRAME); + o->color(FL_BACKGROUND2_COLOR); + o->selection_color(FL_SELECTION_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(14); + o->labelcolor(FL_FOREGROUND_COLOR); + o->textfont(4); + o->textsize(11); + o->align(FL_ALIGN_TOP); + o->when(FL_WHEN_RELEASE); + Fl_Group::current()->resizable(o); + } + o->end(); + } + o->end(); + Fl_Group::current()->resizable(o); + } + { Fl_Group* o = new Fl_Group(20, 460, 500, 25); + { Fl_Button* o = new Fl_Button(20, 460, 80, 25, "refresh"); + o->labelsize(11); + o->callback((Fl_Callback*)update_sourceview_cb); + } + { Fl_Light_Button* o = sv_autorefresh = new Fl_Light_Button(105, 460, 80, 25, "autorefresh"); + o->labelsize(11); + o->callback((Fl_Callback*)update_sourceview_cb); + } + { Fl_Light_Button* o = sv_autoposition = new Fl_Light_Button(190, 460, 80, 25, "autoposition"); + o->labelsize(11); + } + { Fl_Button* o = new Fl_Button(440, 460, 80, 25, "close"); + o->labelsize(11); + o->callback((Fl_Callback*)toggle_sourceview_b_cb); + } + { Fl_Box* o = new Fl_Box(275, 460, 160, 25); + Fl_Group::current()->resizable(o); + } + o->end(); + } + o->size_range(384, 120); + o->end(); + } + return w; +} + // // End of "$Id$". // diff --git a/fluid/function_panel.fl b/fluid/function_panel.fl index e4c668100..032a75f0e 100644 --- a/fluid/function_panel.fl +++ b/fluid/function_panel.fl @@ -28,7 +28,7 @@ comment {// // // http://www.fltk.org/str.php // -} {selected in_source in_header +} {in_source in_header } decl {\#include <FL/Fl_Pixmap.H>} {} @@ -353,9 +353,9 @@ Function {make_widgetbin()} {open } { Fl_Window widgetbin_panel { label {Widget Bin} - xywh {413 185 520 85} type Single hide non_modal + xywh {413 185 520 85} type Single non_modal visible } { - Fl_Group {} {open + Fl_Group {} { xywh {3 3 79 79} box THIN_DOWN_BOX } { Fl_Button {} { @@ -684,6 +684,67 @@ Function {make_widgetbin()} {open } } +Function {make_sourceview()} {open +} { + Fl_Window sourceview_panel { + label {Code View} + callback toggle_sourceview_cb open + xywh {388 212 544 500} type Double resizable size_range {384 120 0 0} visible + } { + Fl_Tabs sv_tab { + callback update_sourceview_position_cb open + xywh {20 10 500 440} resizable + } { + Fl_Group {} { + label Source open + xywh {20 35 500 415} labelsize 13 resizable + } { + Fl_Text_Editor sv_source { + xywh {25 40 490 405} textfont 4 textsize 11 resizable + code0 {\#include "CodeEditor.h"} + class CodeEditor + } + } + Fl_Group {} { + label Header open + xywh {20 35 500 415} labelsize 13 hide + } { + Fl_Text_Editor sv_header { + xywh {25 40 490 405} textfont 4 textsize 11 resizable + code0 {\#include "CodeEditor.h"} + class CodeEditor + } + } + } + Fl_Group {} {open + xywh {20 460 500 25} + } { + Fl_Button {} { + label refresh + callback update_sourceview_cb + xywh {20 460 80 25} labelsize 11 + } + Fl_Light_Button sv_autorefresh { + label autorefresh + xywh {105 460 80 25} labelsize 11 + code0 {o->callback((Fl_Callback*)update_sourceview_cb);} + } + Fl_Light_Button sv_autoposition { + label autoposition + xywh {190 460 80 25} labelsize 11 + } + Fl_Button {} { + label close + callback toggle_sourceview_b_cb selected + xywh {440 460 80 25} labelsize 11 + } + Fl_Box {} { + xywh {275 460 160 25} resizable + } + } + } +} + comment { // // End of "$Id$". diff --git a/fluid/function_panel.h b/fluid/function_panel.h index e0e315e03..cd8c5254c 100644 --- a/fluid/function_panel.h +++ b/fluid/function_panel.h @@ -92,6 +92,18 @@ void type_make_cb(Fl_Widget*w,void*d); extern Fl_Window *widgetbin_panel; extern void type_make_cb(Fl_Button*, void*); Fl_Window* make_widgetbin(); +extern void toggle_sourceview_cb(Fl_Double_Window*, void*); +extern Fl_Double_Window *sourceview_panel; +#include <FL/Fl_Tabs.H> +extern void update_sourceview_position_cb(Fl_Tabs*, void*); +extern Fl_Tabs *sv_tab; +extern CodeEditor *sv_source; +extern CodeEditor *sv_header; +extern void update_sourceview_cb(Fl_Button*, void*); +extern Fl_Light_Button *sv_autorefresh; +extern Fl_Light_Button *sv_autoposition; +extern void toggle_sourceview_b_cb(Fl_Button*, void*); +Fl_Double_Window* make_sourceview(); #endif // |
