display GraphicsEditControl in its own tooltip window avoiding the need to hack FLTKs internals
parent
396b1c63a4
commit
ce77197dac
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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:$".
|
||||
//
|
|
@ -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:$".
|
||||
//
|
Loading…
Reference in New Issue