summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael R Sweet <michael.r.sweet@gmail.com>2005-03-20 17:41:56 +0000
committerMichael R Sweet <michael.r.sweet@gmail.com>2005-03-20 17:41:56 +0000
commit0bc98fd29efa40f4828813fd490c2afe6e2e7c4f (patch)
tree73a27040211c17adb95b79f5ba3510714de570f9
parent4e965380bc872a5da745d64a5d9deb901fa2979c (diff)
Preliminary template save support in FLUID, plus some bug fixes.
fluid/Fl_Type.h: - Added read_image() declaration to Fl_Window_Type class. fluid/Fl_Window_Type.cxx: - Added Overlay_Window::read_image() and Fl_Window_Type::read_image() functions. - Fl_Window_Type::fix_overlay(): update menu indices. - toggle_overlays(): update menu indices. fluid/fluid.cxx: - save_template_cb(): Added to save to ~/.fltk/fltk.org/fluid/templates, along with PNG screenshot of first window. - "Save To" instead of "Save to". - Use fl_alert() for errors, not fl_message(). - Add "File/Save Template..." and "File/Print..." (not yet implemented) menu items. - toggle_widgetbin_cb(): update menu indices. fluid/undo.cxx: - Update menu item indices. - Don't need extra slash in undo checkpoint filename. src/Fl_PNG_Image.cxx: - Fix typo in #endif comment. src/Fl_Window.cxx: - Fl_Window::draw(): save/restore flags() when changing label. - Fl_Window::iconlabel(): save/restore flags() when changing label. src/fl_rect.cxx: - fl_not_clipped(): don't use current window for gross clipping. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.1@4147 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
-rw-r--r--CHANGES5
-rw-r--r--fluid/Fl_Type.h3
-rw-r--r--fluid/Fl_Window_Type.cxx47
-rw-r--r--fluid/fluid.cxx127
-rw-r--r--fluid/undo.cxx6
-rw-r--r--src/Fl_PNG_Image.cxx2
-rw-r--r--src/Fl_Window.cxx8
-rw-r--r--src/fl_rect.cxx8
8 files changed, 187 insertions, 19 deletions
diff --git a/CHANGES b/CHANGES
index 402a3be65..4245128bc 100644
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,11 @@ CHANGES IN FLTK 1.1.7
- Documentation fixes (STR #648, STR #692, STR #730, STR
#744, STR #745)
+ - fl_not_clipped() incorrectly used the current window
+ dimensions for gross clipping, which interfered with
+ off-screen rendering.
+ - Fl_Window::draw() and Fl_Window::iconlabel() could leak
+ memory if copy_label() was used on the window.
- fl_shortcut_label() now shows letter shortcuts in
uppercase, e.g. "Ctrl+N" instead of "Ctrl+n" to be
consistent with other toolkits.
diff --git a/fluid/Fl_Type.h b/fluid/Fl_Type.h
index 535c4a88f..03f7ed3d5 100644
--- a/fluid/Fl_Type.h
+++ b/fluid/Fl_Type.h
@@ -470,7 +470,8 @@ public:
void open();
- void fix_overlay(); // update the bounding box, etc
+ void fix_overlay(); // Update the bounding box, etc
+ uchar *read_image(int &ww, int &hh); // Read an image of the window
virtual void write_properties();
virtual void read_property(const char *);
diff --git a/fluid/Fl_Window_Type.cxx b/fluid/Fl_Window_Type.cxx
index 31cc08601..9f2702b54 100644
--- a/fluid/Fl_Window_Type.cxx
+++ b/fluid/Fl_Window_Type.cxx
@@ -31,6 +31,7 @@
#include <FL/Fl_Overlay_Window.H>
#include <FL/fl_message.H>
#include <FL/fl_draw.H>
+#include <FL/x.H>
#include <FL/Fl_Menu_Item.H>
#include "Fl_Widget_Type.h"
#include "undo.h"
@@ -247,6 +248,7 @@ public:
int handle(int);
Overlay_Window(int W,int H) : Fl_Overlay_Window(W,H) {Fl_Group::current(0);}
void resize(int,int,int,int);
+ uchar *read_image(int &ww, int &hh);
};
void Overlay_Window::draw() {
const int CHECKSIZE = 8;
@@ -264,6 +266,36 @@ void Overlay_Window::draw() {
Fl_Overlay_Window::draw();
}
+extern Fl_Window *main_window;
+
+// Read an image of the overlay window
+uchar *Overlay_Window::read_image(int &ww, int &hh) {
+ // Create an off-screen buffer for the window...
+ main_window->make_current();
+
+ ww = w();
+ hh = h();
+
+ Fl_Offscreen offscreen = fl_create_offscreen(ww, hh);
+ uchar *pixels;
+
+ // Redraw the window into the offscreen buffer...
+ fl_begin_offscreen(offscreen);
+
+ redraw();
+ draw();
+
+ // Read the screen image...
+ pixels = fl_read_image(0, 0, 0, ww, hh);
+
+ fl_end_offscreen();
+
+ // Cleanup and return...
+ fl_delete_offscreen(offscreen);
+
+ return pixels;
+}
+
void Overlay_Window::draw_overlay() {
window->draw_overlay();
}
@@ -341,6 +373,15 @@ void Fl_Window_Type::open() {
w->size_range(gridx, gridy, Fl::w(), Fl::h(), gridx, gridy, 0);
}
+// Read an image of the window
+uchar *Fl_Window_Type::read_image(int &ww, int &hh) {
+ Overlay_Window *w = (Overlay_Window *)o;
+
+ // Read the screen image...
+ return (w->read_image(ww, hh));
+}
+
+
// control panel items:
void modal_cb(Fl_Light_Button* i, void* v) {
@@ -932,7 +973,7 @@ extern Fl_Menu_Item Main_Menu[];
// Calculate new bounding box of selected widgets:
void Fl_Window_Type::fix_overlay() {
- Main_Menu[38].label("Hide O&verlays");
+ Main_Menu[40].label("Hide O&verlays");
overlays_invisible = 0;
recalc = 1;
((Overlay_Window *)(this->o))->redraw_overlay();
@@ -947,8 +988,8 @@ void redraw_overlays() {
void toggle_overlays(Fl_Widget *,void *) {
overlays_invisible = !overlays_invisible;
- if (overlays_invisible) Main_Menu[38].label("Show O&verlays");
- else Main_Menu[38].label("Hide O&verlays");
+ if (overlays_invisible) Main_Menu[40].label("Show O&verlays");
+ else Main_Menu[40].label("Hide O&verlays");
for (Fl_Type *o=Fl_Type::first; o; o=o->next)
if (o->is_window()) {
diff --git a/fluid/fluid.cxx b/fluid/fluid.cxx
index 6cd47e5df..b4fb4907f 100644
--- a/fluid/fluid.cxx
+++ b/fluid/fluid.cxx
@@ -40,6 +40,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
+#include <sys/stat.h>
#include "../src/flstring.h"
#include "alignment_panel.h"
@@ -61,6 +62,18 @@
#include "Fl_Type.h"
+extern "C"
+{
+#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ)
+# include <zlib.h>
+# ifdef HAVE_PNG_H
+# include <png.h>
+# else
+# include <libpng/png.h>
+# endif // HAVE_PNG_H
+#endif // HAVE_LIBPNG && HAVE_LIBZ
+}
+
static Fl_Help_Dialog *help_dialog = 0;
Fl_Preferences fluid_prefs(Fl_Preferences::USER, "fltk.org", "fluid");
@@ -145,12 +158,11 @@ void save_cb(Fl_Widget *, void *v) {
const char *c = filename;
if (v || !c || !*c) {
fl_ok = "Save";
- c=fl_file_chooser("Save to:", "FLUID Files (*.f[ld])", c);
+ c=fl_file_chooser("Save To:", "FLUID Files (*.f[ld])", c);
fl_ok = "OK";
if (!c) return;
- if (!access(c, 0))
- {
+ if (!access(c, 0)) {
const char *basename;
if ((basename = strrchr(c, '/')) != NULL)
basename ++;
@@ -169,13 +181,112 @@ void save_cb(Fl_Widget *, void *v) {
set_filename(c);
}
if (!write_file(c)) {
- fl_message("Error writing %s: %s", c, strerror(errno));
+ fl_alert("Error writing %s: %s", c, strerror(errno));
return;
}
set_modflag(0);
undo_save = undo_current;
}
+void save_template_cb(Fl_Widget *, void *) {
+ const char *c = fl_input("Template Name:");
+ if (!c) return;
+
+ char filename[1024];
+ fluid_prefs.getUserdataPath(filename, sizeof(filename));
+
+ strlcat(filename, "templates", sizeof(filename));
+ if (access(filename, 0)) mkdir(filename, 0777);
+
+ strlcat(filename, "/", sizeof(filename));
+ strlcat(filename, c, sizeof(filename));
+
+ char *ext = filename + strlen(filename);
+ if (ext >= (filename + sizeof(filename) - 5)) {
+ fl_alert("The template name \"%s\" is too long!", c);
+ return;
+ }
+
+ strcpy(ext, ".fl");
+
+// printf("save_template_cb: template filename=\"%s\"\n", filename);
+
+ if (!access(filename, 0)) {
+ if (fl_choice("The template \"%s\" already exists.\n"
+ "Do you want to replace it?", "Cancel",
+ "Replace", NULL, c) == 0) return;
+ }
+
+ if (!write_file(filename)) {
+ fl_alert("Error writing %s: %s", filename, strerror(errno));
+ return;
+ }
+
+#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ)
+ // Get the screenshot, if any...
+ Fl_Type *t;
+
+ for (t = Fl_Type::first; t; t = t->next) {
+ // Find the first window...
+ if (t->is_window()) break;
+ }
+
+ if (!t) return;
+
+ // Grab a screenshot...
+ Fl_Window_Type *wt = (Fl_Window_Type *)t;
+ uchar *pixels;
+ int w, h;
+
+ if ((pixels = wt->read_image(w, h)) == NULL) return;
+
+// printf("save_template_cb: pixels=%p, w=%d, h=%d...\n", pixels, w, h);
+
+ // Save to a PNG file...
+ strcpy(ext, ".png");
+
+// printf("save_template_cb: screenshot filename=\"%s\"\n", filename);
+
+ FILE *fp;
+
+ if ((fp = fopen(filename, "wb")) == NULL) {
+ delete[] pixels;
+ fl_alert("Error writing %s: %s", filename, strerror(errno));
+ return;
+ }
+
+ png_structp pptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
+ png_infop iptr = png_create_info_struct(pptr);
+ png_bytep ptr = (png_bytep)pixels;
+
+ png_init_io(pptr, fp);
+ png_set_IHDR(pptr, iptr, w, h, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+ png_set_sRGB(pptr, iptr, PNG_sRGB_INTENT_PERCEPTUAL);
+
+ png_write_info(pptr, iptr);
+
+ for (int i = h; i > 0; i --, ptr += w * 3) {
+ png_write_row(pptr, ptr);
+ }
+
+ png_write_end(pptr, iptr);
+ png_destroy_write_struct(&pptr, &iptr);
+
+ fclose(fp);
+
+# if 0 // The original PPM output code...
+ strcpy(ext, ".ppm");
+ fp = fopen(filename, "wb");
+ fprintf(fp, "P6\n%d %d 255\n", w, h);
+ fwrite(pixels, w * h, 3, fp);
+ fclose(fp);
+# endif // 0
+
+ delete[] pixels;
+#endif // HAVE_LIBPNG && HAVE_LIBZ
+}
+
void exit_cb(Fl_Widget *,void *) {
if (modflag)
switch (fl_choice("Do you want to save changes to this user\n"
@@ -607,7 +718,7 @@ Fl_Menu_Item Main_Menu[] = {
{"&File",0,0,0,FL_SUBMENU},
{"&New", FL_CTRL+'n', new_cb, 0},
{"&Open...", FL_CTRL+'o', open_cb, 0},
- {"Open &Previous",0,0,0,FL_SUBMENU},
+ {"Open Pre&vious",0,0,0,FL_SUBMENU},
{relative_history[0], FL_CTRL+'0', open_history_cb, absolute_history[0]},
{relative_history[1], FL_CTRL+'1', open_history_cb, absolute_history[1]},
{relative_history[2], FL_CTRL+'2', open_history_cb, absolute_history[2]},
@@ -622,6 +733,8 @@ Fl_Menu_Item Main_Menu[] = {
{"&Insert...", FL_CTRL+'i', open_cb, (void*)1, FL_MENU_DIVIDER},
{"&Save", FL_CTRL+'s', save_cb, 0},
{"Save &As...", FL_CTRL+FL_SHIFT+'s', save_cb, (void*)1},
+ {"Save &Template...", 0, save_template_cb, (void*)2, FL_MENU_DIVIDER},
+ {"&Print...", FL_CTRL+'p', 0},
{"Write &Code...", FL_CTRL+FL_SHIFT+'c', write_cb, 0},
{"&Write Strings...", FL_CTRL+FL_SHIFT+'w', write_strings_cb, 0, FL_MENU_DIVIDER},
{"&Quit", FL_CTRL+'q', exit_cb},
@@ -721,10 +834,10 @@ void toggle_widgetbin_cb(Fl_Widget *, void *) {
if (widgetbin_panel->visible()) {
widgetbin_panel->hide();
- Main_Menu[39].label("Show Widget &Bin...");
+ Main_Menu[41].label("Show Widget &Bin...");
} else {
widgetbin_panel->show();
- Main_Menu[39].label("Hide Widget &Bin");
+ Main_Menu[41].label("Hide Widget &Bin");
}
}
diff --git a/fluid/undo.cxx b/fluid/undo.cxx
index 9aae0ac08..1982ffa7e 100644
--- a/fluid/undo.cxx
+++ b/fluid/undo.cxx
@@ -41,8 +41,8 @@
extern Fl_Preferences fluid_prefs; // FLUID preferences
extern Fl_Menu_Item Main_Menu[]; // Main menu
-#define UNDO_ITEM 23 // Undo menu item index
-#define REDO_ITEM 24 // Redo menu item index
+#define UNDO_ITEM 25 // Undo menu item index
+#define REDO_ITEM 26 // Redo menu item index
//
@@ -67,7 +67,7 @@ static char *undo_filename(int level, char *buf, int bufsize) {
if (!undo_path[0]) fluid_prefs.getUserdataPath(undo_path, sizeof(undo_path));
- snprintf(buf, bufsize, "%s/undo_%d_%d.fl", undo_path, getpid(), level);
+ snprintf(buf, bufsize, "%sundo_%d_%d.fl", undo_path, getpid(), level);
return buf;
}
diff --git a/src/Fl_PNG_Image.cxx b/src/Fl_PNG_Image.cxx
index d07a37dfd..3aa76e4b5 100644
--- a/src/Fl_PNG_Image.cxx
+++ b/src/Fl_PNG_Image.cxx
@@ -47,7 +47,7 @@ extern "C"
# else
# include <libpng/png.h>
# endif // HAVE_PNG_H
-#endif // HAVE_LIBPNG ** HAVE_LIBZ
+#endif // HAVE_LIBPNG && HAVE_LIBZ
}
diff --git a/src/Fl_Window.cxx b/src/Fl_Window.cxx
index 414074138..f8fb10253 100644
--- a/src/Fl_Window.cxx
+++ b/src/Fl_Window.cxx
@@ -92,6 +92,7 @@ int Fl_Window::y_root() const {
void Fl_Window::draw() {
const char *savelabel = label();
+ uchar saveflags = flags();
int savex = x(); x(0);
int savey = y(); y(0);
// Make sure we don't draw the window title in the window background...
@@ -99,13 +100,18 @@ void Fl_Window::draw() {
Fl_Group::draw();
// Restore the label...
Fl_Widget::label(savelabel);
+ set_flag(saveflags);
y(savey);
x(savex);
}
void Fl_Window::label(const char *name) {label(name, iconlabel());}
-void Fl_Window::iconlabel(const char *iname) {label(label(), iname);}
+void Fl_Window::iconlabel(const char *iname) {
+ uchar saveflags = flags();
+ label(label(), iname);
+ set_flag(saveflags);
+}
// the Fl::atclose pointer is provided for back compatability. You
// can now just change the callback for the window instead.
diff --git a/src/fl_rect.cxx b/src/fl_rect.cxx
index 272c45332..a1c06f3b6 100644
--- a/src/fl_rect.cxx
+++ b/src/fl_rect.cxx
@@ -29,6 +29,7 @@
// that minimal update works.
#include <config.h>
+#include <FL/Fl.H>
#include <FL/Fl_Widget.H>
#include <FL/fl_draw.H>
#include <FL/x.H>
@@ -534,12 +535,14 @@ void fl_push_clip(int x, int y, int w, int h) {
#endif
}
if (rstackptr < STACK_MAX) rstack[++rstackptr] = r;
+ else Fl::warning("fl_push_clip: clip stack overflow!\n");
fl_restore_clip();
}
// make there be no clip (used by fl_begin_offscreen() only!)
void fl_push_no_clip() {
if (rstackptr < STACK_MAX) rstack[++rstackptr] = 0;
+ else Fl::warning("fl_push_no_clip: clip stack overflow!\n");
fl_restore_clip();
}
@@ -548,14 +551,13 @@ void fl_pop_clip() {
if (rstackptr > 0) {
Fl_Region oldr = rstack[rstackptr--];
if (oldr) XDestroyRegion(oldr);
- }
+ } else Fl::warning("fl_pop_clip: clip stack underflow!\n");
fl_restore_clip();
}
// does this rectangle intersect current clip?
int fl_not_clipped(int x, int y, int w, int h) {
- if (x+w <= 0 || y+h <= 0 || x > Fl_Window::current()->w()
- || y > Fl_Window::current()->h()) return 0;
+ if (x+w <= 0 || y+h <= 0) return 0;
Fl_Region r = rstack[rstackptr];
#ifdef WIN32
if (!r) return 1;