display GraphicsEditControl in its own tooltip window avoiding the need to hack FLTKs internals

pull/3/head
Andrew Downing 2015-02-25 12:43:01 -05:00
parent 396b1c63a4
commit ce77197dac
4 changed files with 72 additions and 394 deletions

View File

@ -77,8 +77,6 @@ solvespace_SOURCES = \
if HAVE_FLTK
solvespace_SOURCES += \
fltk/xFl_Gl_Window_Group.H \
fltk/xFl_Gl_Window_Group.cxx \
fltk/fltkmain.cpp \
fltk/fltkutil.cpp

View File

@ -26,12 +26,13 @@
# endif
#endif
#include <fltk/xFl_Gl_Window_Group.H> //#include <FL/Fl_Gl_Window_Group.H>
#include <FL/Fl_Gl_Window.H>
#include <FL/Fl_Native_File_Chooser.H>
#include <FL/Fl_Preferences.H>
#include <FL/Fl_Sys_Menu_Bar.H>
#include <FL/forms.H> // for fl_gettime()
#include <FL/gl.h>
#include <FL/names.h>
#include "solvespace.h"
@ -44,6 +45,7 @@ class Text_Gl_Window;
static Fl_Window *GraphicsWnd = NULL;
static Graphics_Gl_Window *GraphicsGlWnd = NULL;
static Fl_Window *GraphicsEditControlWindow = NULL;
static Fl_Input *GraphicsEditControl = NULL;
static Fl_Sys_Menu_Bar *MenuBar = NULL;
static Fl_Menu_Item MenuBarItems[120];
@ -359,16 +361,24 @@ int64_t GetUnixTime(void)
return (int64_t)ret;
}
class Graphics_Gl_Window : public Fl_Gl_Window_Group
class Graphics_Gl_Window : public Fl_Gl_Window
{
public:
Graphics_Gl_Window(int x, int y, int w, int h)
: Fl_Gl_Window_Group(x, y, w, h)
: Fl_Gl_Window(x, y, w, h)
{
mode(FL_RGB | FL_DOUBLE);
}
virtual int handle(int event) {
if(handle_gl(event) == 0) {
return Fl_Gl_Window::handle(event);
} else {
return 1;
}
}
int handle_gl(int event)
{
switch(event)
@ -524,7 +534,16 @@ public:
return 0;
}
virtual void resize(int x, int y,int w, int h) {
Fl_Window::resize(x, y, w, h);
}
protected:
virtual void draw() {
if(damage()) {
draw_gl();
}
}
void draw_gl(void)
{
@ -608,16 +627,24 @@ bool MenuBarIsVisible(void)
return MenuBarVisible;
}
class Text_Gl_Window : public Fl_Gl_Window_Group
class Text_Gl_Window : public Fl_Gl_Window
{
public:
Text_Gl_Window(int x, int y, int w, int h)
: Fl_Gl_Window_Group(x, y, w, h)
: Fl_Gl_Window(x, y, w, h)
{
mode(FL_RGB | FL_DOUBLE);
}
virtual int handle(int event) {
if(handle_gl(event) == 0) {
return Fl_Gl_Window::handle(event);
} else {
return 1;
}
}
int handle_gl(int event)
{
switch(event)
@ -657,7 +684,16 @@ public:
return 0;
}
virtual void resize(int x, int y,int w, int h) {
Fl_Window::resize(x, y, w, h);
}
protected:
virtual void draw() {
if(damage()) {
draw_gl();
}
}
void draw_gl(void)
{
@ -713,12 +749,11 @@ void ShowGraphicsEditControl(int x, int y, char *s)
// Convert to ij (vs. xy) style coordinates,
// and compensate for the input widget height due to inverse coord
x = x + GraphicsGlWnd->w()/2;
y = -y + GraphicsGlWnd->h()/2 - GraphicsEditControl->h();
y = -y + GraphicsGlWnd->h()/2 - GraphicsEditControlWindow->h();
// Use of the :: 0perator to avoid confusion with the Fl_input positon metod.
GraphicsEditControl->Fl_Widget::position(x, y);
GraphicsEditControlWindow->position(x, y);
GraphicsEditControl->value(s);
GraphicsEditControl->show();
GraphicsEditControlWindow->show();
// Grab focus and select all to ease editing
GraphicsEditControl->take_focus();
@ -733,12 +768,12 @@ void HideGraphicsEditControl(void)
// this avoid the disapparition of the mouse pointer if it was over the widget
GraphicsGlWnd->take_focus();
GraphicsEditControl->hide();
GraphicsEditControlWindow->hide();
}
bool GraphicsEditControlIsVisible(void)
{
return GraphicsEditControl->visible();
return GraphicsEditControlWindow->visible();
}
void InvalidateText(void)
@ -768,6 +803,9 @@ static void WindowCloseHandler(Fl_Window *wnd, void *data)
if(wnd == GraphicsWnd) {
SolveSpace::MenuFile(GraphicsWindow::MNU_EXIT);
}
else if(wnd == GraphicsEditControlWindow) {
HideGraphicsEditControl();
}
else if(wnd == TextWnd) {
if(SS.GW.showTextWindow) {
GraphicsWindow::MenuView(GraphicsWindow::MNU_SHOW_TEXT_WND);
@ -1123,14 +1161,33 @@ static void CreateMainWindows(void)
GraphicsWnd->resizable(GraphicsGlWnd);
GraphicsWnd->size_range(Fl::w() / 4, Fl::h() / 4);
GraphicsEditControl = new Fl_Input(0, 20, 120, 30);
GraphicsGlWnd->end();
GraphicsWnd->end();
int w = 120;
int h = 30;
int padding = 5;
GraphicsEditControlWindow = new Fl_Window(
w + (padding * 2), h + (padding * 2),
""
);
GraphicsEditControlWindow->set_tooltip_window();
GraphicsEditControl = new Fl_Input(
(GraphicsEditControlWindow->w() / 2) - (w / 2),
(GraphicsEditControlWindow->h() / 2) - (h / 2),
w,
h
);
GraphicsEditControl->textfont(SS_FONT_MONOSPACE);
GraphicsEditControl->callback(EditControlCallback);
GraphicsEditControl->when(FL_WHEN_ENTER_KEY | FL_WHEN_NOT_CHANGED);
GraphicsEditControl->hide();
GraphicsGlWnd->end();
GraphicsWnd->end();
GraphicsEditControlWindow->end();
GraphicsEditControlWindow->hide();
// Text window

View File

@ -1,105 +0,0 @@
//
// "$Id$"
//
// OpenGL window group widget for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2010 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
// file is missing or damaged, see the license at:
//
// http://www.fltk.org/COPYING.php
//
// Please report all bugs and problems on the following page:
//
// http://www.fltk.org/str.php
//
/* \file
Fl_Gl_Window_Group widget . */
#ifndef Fl_Gl_Window_Group_H
#define Fl_Gl_Window_Group_H
#include <FL/Fl_Gl_Window.H> //#include "Fl_Gl_Window.H"
#include <FL/x.H> //#include "x.H"
#define Fl_Gl_Window_Group xFl_Gl_Window_Group
class Fl_Gl_Window_Group_INTERNAL;
/**
The Fl_Gl_Window_Group widget is an extended form of Fl_Gl_Window that
can contain child widgets not specially modified to use OpenGL calls.
After the main OpenGL area is drawn, child widgets are each drawn into an
offscreen buffer (using the standard FLTK drawing routines), and then
copied into the OpenGL window using a textured quad.
*/
class FL_EXPORT Fl_Gl_Window_Group : public Fl_Gl_Window {
class Fl_Gl_Window_Group_INTERNAL *glstandin;
Fl_Offscreen offscr;
int offscr_w, offscr_h;
uchar *imgbuf;
unsigned int texid;
void init(void);
void adjust_offscr(int w, int h);
public:
~Fl_Gl_Window_Group(void);
/**
Creates a new Fl_Gl_Window_Group widget using the given size and label string.
*/
Fl_Gl_Window_Group(int W, int H, const char *l=0)
: Fl_Gl_Window(W,H,l) {init();}
/**
Creates a new Fl_Gl_Window_Group widget using the given position,
size, and label string.
*/
Fl_Gl_Window_Group(int X, int Y, int W, int H, const char *l=0)
: Fl_Gl_Window(X,Y,W,H,l) {init();}
void show(void);
void hide(void);
void clear(void);
void flush(void);
/**
Handles the specified event.
This method only receives events that were not used by any of the child
widgets. Unlike most handle() methods, this should not call the
inherited handle() method, or else an infinite loop will result.
*/
virtual int handle_gl(int event);
// override resize
virtual void resize(int x, int y,int w, int h);
protected:
void draw(void);
void draw_children(void);
void draw_child(Fl_Widget& widget);
/**
Draws the main OpenGL area of the Fl_Gl_Window_Group.
You \e \b must override the draw_gl() method.
*/
virtual void draw_gl(void);
};
#endif
//
// End of "$Id:$".
//

View File

@ -1,272 +0,0 @@
//
// "$Id$"
//
// OpenGL window group widget for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2010 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
// file is missing or damaged, see the license at:
//
// http://www.fltk.org/COPYING.php
//
// Please report all bugs and problems on the following page:
//
// http://www.fltk.org/str.php
//
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <FL/Fl.H>
#include <FL/Fl_Box.H>
#include <FL/fl_draw.H>
#include <FL/gl.h>
#include <fltk/xFl_Gl_Window_Group.H>
#if 1 //HAVE_GL
#if !defined(GL_TEXTURE_RECTANGLE) && defined(WIN32)
# define GL_TEXTURE_RECTANGLE 0x84F5
#endif
#define Gl_Stand_In Fl_Gl_Window_Group_INTERNAL
#define RESET_FIELDS() \
imgbuf = NULL; \
offscr_w = -1; \
offscr_h = -1
class Gl_Stand_In : public Fl_Box {
Fl_Gl_Window_Group *glwg;
public:
Gl_Stand_In(int W, int H, Fl_Gl_Window_Group *w)
: Fl_Box(0, 0, W, H) {
glwg = w;
}
int handle(int event) { return glwg->handle_gl(event); }
protected:
void draw(void) { Fl::fatal("Never call this"); }
virtual void dummy(void);
};
void Gl_Stand_In::dummy(void) {}
void Fl_Gl_Window_Group::init(void) {
begin(); // Revert the end() in the Fl_Gl_Window constructor
glstandin = new Gl_Stand_In(w(), h(), this);
texid = 0;
RESET_FIELDS();
}
Fl_Gl_Window_Group::~Fl_Gl_Window_Group(void) {
delete glstandin;
}
void Fl_Gl_Window_Group::adjust_offscr(int w, int h) {
if (imgbuf == NULL) {
// Find maximum width and height across all visible child widgets
// (except for the GL stand-in widget)
Fl_Widget*const* a = array();
for (int i = children(); i--;) {
Fl_Widget* o = a[i];
if (o == glstandin) continue;
if (!o->visible()) continue;
int cw = o->w();
int ch = o->h();
if (offscr_w < cw) offscr_w = cw;
if (offscr_h < ch) offscr_h = ch;
}
} else {
fl_delete_offscreen(offscr);
}
if (w > offscr_w) offscr_w = w;
if (h > offscr_h) offscr_h = h;
offscr = fl_create_offscreen(offscr_w, offscr_h);
int imgbuf_size = offscr_w * offscr_h * 3; // GL_RGB
imgbuf = (uchar *)realloc(imgbuf, (size_t)imgbuf_size);
}
void Fl_Gl_Window_Group::show() {
Fl_Gl_Window::show();
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glEnable(GL_TEXTURE_RECTANGLE);
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glGenTextures(1, &texid);
glBindTexture(GL_TEXTURE_RECTANGLE, texid);
make_current();
}
void Fl_Gl_Window_Group::hide() {
glDeleteTextures(1, &texid);
texid = 0;
make_current();
Fl_Gl_Window::hide();
}
/**
Deletes all child widgets from memory recursively.
This method differs from the remove() method in that it
affects all child widgets and deletes them from memory.
*/
void Fl_Gl_Window_Group::clear(void) {
if (imgbuf != NULL) {
fl_delete_offscreen(offscr);
free(imgbuf);
RESET_FIELDS();
}
remove(glstandin);
Fl_Gl_Window::clear();
add(glstandin);
}
int Fl_Gl_Window_Group::handle_gl(int event) {
// Override me
return 0;
}
void Fl_Gl_Window_Group::resize(int x, int y,int w, int h)
{
glstandin->resize(x,y,w,h);
Fl_Window::resize(x,y,w,h);
}
void Fl_Gl_Window_Group::flush(void) {
// Fl_Window::make_current() does this, but not
// Fl_Gl_Window::make_current(), and we can't override make_current()
// and have Fl_Gl_Window::flush() call us
Fl_Window::make_current();
Fl_Gl_Window::make_current();
Fl_Gl_Window::flush();
}
void Fl_Gl_Window_Group::draw(void) {
if (damage()) {
draw_gl();
draw_children();
}
}
/**
Draws all children of the group.
*/
void Fl_Gl_Window_Group::draw_children(void) {
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glOrtho(0, w(), 0, h(), -1.0, 1.0);
glTranslatef(0.0, h(), 0.0);
glScalef(1.0, -1.0, 1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, w(), h());
Fl_Widget*const* a = array();
for (int i = children(); i--;) draw_child(**a++);
#if 1
int err = glGetError();
if (err != GL_NO_ERROR) {
Fl::warning("OpenGL error after drawing Fl_Gl_Window_Group children: 0x0%X", err);
}
#endif
make_current();
}
/**
This draws a child widget, if it is not clipped.
The damage bits are cleared after drawing.
*/
void Fl_Gl_Window_Group::draw_child(Fl_Widget& widget) {
if (&widget == glstandin) return;
if (!widget.visible() || widget.type() >= FL_WINDOW ||
!fl_not_clipped(widget.x(), widget.y(), widget.w(), widget.h())) return;
if (widget.w() > offscr_w || widget.h() > offscr_h) {
adjust_offscr(widget.w(), widget.h());
}
int widget_x = widget.x();
int widget_y = widget.y();
int widget_w = widget.w();
int widget_h = widget.h();
widget.position(0, 0);
fl_begin_offscreen(offscr);
fl_rectf(0, 0, widget_w, widget_h, FL_MAGENTA);
widget.clear_damage(FL_DAMAGE_ALL);
widget.draw();
widget.clear_damage();
fl_read_image(imgbuf, 0, 0, widget_w, widget_h);
fl_end_offscreen();
widget.position(widget_x, widget_y);
#ifdef USE_GLDRAWPIXELS // Note: glDrawPixels() is deprecated
glRasterPos2i(widget_x, widget_y);
glPixelZoom(1.0, -1.0);
glDrawPixels(widget_w, widget_h, GL_RGB, GL_UNSIGNED_BYTE, imgbuf);
#else // ! USE_GLDRAWPIXELS
glTexImage2D(
GL_TEXTURE_RECTANGLE,
0,
GL_RGB,
widget_w, widget_h,
0,
GL_RGB,
GL_UNSIGNED_BYTE,
imgbuf);
#define CORNER(x,y) glTexCoord2f(x, y); glVertex2f(widget_x + x, widget_y + y)
glBegin(GL_QUADS);
CORNER(0, 0);
CORNER(widget_w, 0);
CORNER(widget_w, widget_h);
CORNER(0, widget_h);
glEnd();
#undef CORNER
#endif // ! USE_GLDRAWPIXELS
}
void Fl_Gl_Window_Group::draw_gl(void) {
Fl::fatal("Fl_Gl_Window_Group::draw_gl() *must* be overriden. Please refer to the documentation.");
}
#else // ! HAVE_GL
typedef int no_opengl_support;
#endif // ! HAVE_GL
//
// End of "$Id:$".
//