917 lines
28 KiB
C++
917 lines
28 KiB
C++
/*
|
|
This file is part of P-GUIDE -
|
|
PUI-based Graphical User Interface Designer.
|
|
Copyright (C) 2002, 2006 John F. Fay
|
|
|
|
P-GUIDE is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
P-GUIDE is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with P-GUIDE; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
$Id: pGuide.cxx 2083 2006-05-01 13:14:50Z bram $
|
|
*/
|
|
|
|
#ifdef VERSION
|
|
#undef VERSION
|
|
#endif
|
|
|
|
#define VERSION = "0.1a"
|
|
|
|
// Program to allow the user to build a PUI Graphical User Interface
|
|
|
|
#include "WidgetList.h"
|
|
|
|
WidgetList *widgets = (WidgetList *)NULL ;
|
|
int max_layer = 1 ;
|
|
|
|
puObject *active_object = (puObject *)NULL ;
|
|
WidgetList *active_widget = (WidgetList *)NULL ;
|
|
static short activity_flag = 0 ; // 0 - inactive; 1 - moving; 2 - resizing xmin, 3 - resizing ymin, 4 - resizing xmax, 5 - resizing ymax
|
|
static int resize_symmetric = 1 ;
|
|
static int resize_corner = 0 ;
|
|
|
|
static int mouse_x_position_in_object = 0 ;
|
|
static int mouse_y_position_in_object = 0 ;
|
|
|
|
static int pguide_last_buttons = 0 ; // Because puMouse isn't called, we have to do our own last_buttons checking
|
|
|
|
// Main window parameters
|
|
int main_window = 0 ; // Main window handle
|
|
int main_window_width = 600 ;
|
|
int main_window_height = 600 ;
|
|
char main_window_name [ PUSTRING_MAX ] ;
|
|
int main_window_x = 0, main_window_y = 0 ;
|
|
|
|
float main_window_color_r = 1.0, main_window_color_g = 1.0,
|
|
main_window_color_b = 1.0, main_window_color_a = 1.0 ;
|
|
|
|
bool main_window_changed = false ;
|
|
static bool done_first_setup = false ;
|
|
bool currently_loading = false ;
|
|
|
|
static int ctrl_key_down = 0 ;
|
|
|
|
static int mouse_x = 0 ;
|
|
static int mouse_y = 0 ;
|
|
|
|
char pguide_current_directory [ PUSTRING_MAX ] ;
|
|
|
|
// Widget count
|
|
int widget_number = 0 ;
|
|
|
|
// Upon creation of new widgets, should they automatically be made "locked"?
|
|
bool autolock = false ;
|
|
|
|
// Properties popup
|
|
static puPopupMenu *context_menu;
|
|
|
|
// From the status window:
|
|
extern void setStatusWidgets ( WidgetList *wid ) ;
|
|
|
|
// From the properties window:
|
|
extern int properties_window;
|
|
|
|
// Definitions
|
|
#define RESIZING_BORDER_WIDTH 5
|
|
#define RESIZING_CORNER_BORDER_WIDTH 4
|
|
/** 4 seems to be the best number for this define... this makes sure *
|
|
* that the default widget size allows you to still resize along the *
|
|
* X axis without difficulty - 23 Jan 03 JCJ **/
|
|
|
|
|
|
// Properties Callback
|
|
|
|
static void cb_edit_properties ( puObject *ob )
|
|
{
|
|
if (properties_window)
|
|
{
|
|
extern puGroup *properties_group;
|
|
/* Delete the widgets */
|
|
puDeleteObject( properties_group );
|
|
glutDestroyWindow( properties_window );
|
|
properties_window = 0;
|
|
glutSetWindow( main_window );
|
|
}
|
|
extern int define_properties_window () ;
|
|
// Open the properties menu
|
|
define_properties_window();
|
|
}
|
|
|
|
static void cb_lock_toggle ( puObject *ob )
|
|
{
|
|
WidgetList *wid = widgets ;
|
|
while ( wid )
|
|
{
|
|
if ( wid->obj == active_object )
|
|
{
|
|
if (wid->locked == false)
|
|
wid->locked = true ;
|
|
else
|
|
wid->locked = false ;
|
|
}
|
|
wid = wid->next ;
|
|
}
|
|
}
|
|
|
|
static void cb_popup_delete ( puObject *ob )
|
|
{
|
|
WidgetList *wid = widgets ;
|
|
WidgetList *prv = (WidgetList *)NULL ;
|
|
while ( wid )
|
|
{
|
|
if ( wid->obj == active_object )
|
|
{
|
|
if ( prv ) // Remove the widget from the linked list
|
|
prv->next = wid->next ;
|
|
else
|
|
widgets = wid->next ;
|
|
|
|
delete wid->object_type_name ; // Delete the widget
|
|
delete wid->legend_text ;
|
|
delete wid->label_text ;
|
|
delete wid->obj ;
|
|
delete wid->allowed ;
|
|
delete wid->items ;
|
|
delete wid ;
|
|
active_widget = (WidgetList *)NULL ;
|
|
active_object = (puObject *)NULL ;
|
|
wid = (WidgetList *)NULL ;
|
|
if (properties_window)
|
|
{
|
|
extern puGroup *properties_group;
|
|
/* Delete the widgets */
|
|
puDeleteObject( properties_group );
|
|
glutDestroyWindow( properties_window );
|
|
properties_window = 0;
|
|
glutSetWindow( main_window );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
prv = wid ;
|
|
wid = wid->next ;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// GLUT Main Window Callbacks
|
|
|
|
static void process_key ( int key )
|
|
{
|
|
extern int selected_object_type ;
|
|
extern puButton *active_button ;
|
|
|
|
ctrl_key_down = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ;
|
|
#define NUDGE_DISTANCE 1
|
|
#define LARGE_NUDGE_DISTANCE 10
|
|
|
|
if ( active_object ) // Active object; check the keys
|
|
{
|
|
main_window_changed = true ;
|
|
|
|
int xo, yo ;
|
|
active_object->getPosition ( &xo, &yo ) ;
|
|
int dist = ctrl_key_down ? LARGE_NUDGE_DISTANCE : NUDGE_DISTANCE ;
|
|
|
|
if ( key == GLUT_KEY_LEFT )
|
|
active_object->setPosition ( xo-dist, yo ) ;
|
|
else if ( key == GLUT_KEY_RIGHT )
|
|
active_object->setPosition ( xo+dist, yo ) ;
|
|
else if ( key == GLUT_KEY_UP )
|
|
active_object->setPosition ( xo, yo+dist ) ;
|
|
else if ( key == GLUT_KEY_DOWN )
|
|
active_object->setPosition ( xo, yo-dist ) ;
|
|
else if ( ( key == 127 ) || ( key == 8 ) ) // Delete or Backspace
|
|
{
|
|
WidgetList *wid = widgets ;
|
|
WidgetList *prv = (WidgetList *)NULL ;
|
|
while ( wid )
|
|
{
|
|
if ( wid->obj == active_object )
|
|
{
|
|
if ( prv ) // Remove the widget from the linked list
|
|
prv->next = wid->next ;
|
|
else
|
|
widgets = wid->next ;
|
|
|
|
delete wid->object_type_name ; // Delete the widget
|
|
delete wid->legend_text ;
|
|
delete wid->label_text ;
|
|
delete wid->obj ;
|
|
delete wid->allowed ;
|
|
delete wid->items ;
|
|
delete wid ;
|
|
active_widget = (WidgetList *)NULL ;
|
|
active_object = (puObject *)NULL ;
|
|
wid = (WidgetList *)NULL ;
|
|
}
|
|
else
|
|
{
|
|
prv = wid ;
|
|
wid = wid->next ;
|
|
}
|
|
}
|
|
}
|
|
else if ( key == 27 ) // Escape key, deactivate the object
|
|
{
|
|
active_widget = (WidgetList *)NULL ;
|
|
active_object = (puObject *)NULL ;
|
|
}
|
|
|
|
setStatusWidgets ( active_widget ) ;
|
|
}
|
|
|
|
if ( selected_object_type )
|
|
{
|
|
if ( key == 27 ) // Escape key, deactivate the selected button
|
|
{
|
|
selected_object_type = 0 ;
|
|
active_button->setValue ( 0 ) ;
|
|
}
|
|
}
|
|
|
|
glutPostRedisplay () ;
|
|
}
|
|
|
|
static void main_window_specialfn ( int key, int, int )
|
|
{
|
|
process_key ( key ) ;
|
|
}
|
|
|
|
static void main_window_keyfn ( unsigned char key, int, int )
|
|
{
|
|
process_key ( key ) ;
|
|
}
|
|
|
|
static void main_window_motionfn ( int x, int yy )
|
|
{
|
|
int y = main_window_height - yy ;
|
|
|
|
mouse_x = x ;
|
|
mouse_y = y ;
|
|
|
|
// Dragging the mouse: If there is an active object, slide it around
|
|
if ( ( active_object ) && ( pguide_last_buttons != 4 ) )
|
|
{
|
|
WidgetList *wid = widgets ;
|
|
while ( wid )
|
|
{
|
|
if ( wid->obj == active_object )
|
|
{
|
|
if (wid->locked == false)
|
|
{
|
|
extern puInput *object_position_x ;
|
|
extern puInput *object_position_y ;
|
|
extern puInput *object_size_x ;
|
|
extern puInput *object_size_y ;
|
|
|
|
main_window_changed = true ;
|
|
|
|
int dist ;
|
|
int xo, yo ;
|
|
active_object->getPosition ( &xo, &yo ) ;
|
|
int w, h ;
|
|
active_object->getSize ( &w, &h ) ;
|
|
|
|
if (resize_corner == 1)
|
|
{
|
|
switch ( activity_flag )
|
|
{
|
|
case 2 : // Resize top-right
|
|
case 3 :
|
|
activity_flag = 6;
|
|
break ;
|
|
|
|
case 4 : // Resize bottom_left
|
|
case 5 :
|
|
activity_flag = 7;
|
|
break ;
|
|
}
|
|
}
|
|
|
|
switch ( activity_flag )
|
|
{
|
|
case 1 : // Moving the object
|
|
active_object->setPosition ( x - mouse_x_position_in_object,
|
|
y - mouse_y_position_in_object ) ;
|
|
break ;
|
|
|
|
case 2 : // Resizing on x-min
|
|
dist = x - xo ;
|
|
if (w - dist < 5) break ;
|
|
if ( resize_symmetric * dist > w ) dist = w / resize_symmetric - 1 ;
|
|
active_object->setPosition ( x, yo ) ;
|
|
active_object->setSize ( w - resize_symmetric * dist, h ) ;
|
|
break ;
|
|
|
|
case 3 : // Resizing on y-min
|
|
dist = y - yo ;
|
|
if (h - dist < 5) break ;
|
|
if ( resize_symmetric * dist > h ) dist = h / resize_symmetric - 1 ;
|
|
active_object->setPosition ( xo, y ) ;
|
|
active_object->setSize ( w, h - resize_symmetric * dist ) ;
|
|
break ;
|
|
|
|
case 4 : // Resizing on x-max
|
|
dist = x - xo - w ;
|
|
if (w + dist < 5) break ;
|
|
if ( resize_symmetric * dist < -w ) dist = 1 - w / resize_symmetric ;
|
|
active_object->setSize ( w + resize_symmetric * dist, h ) ;
|
|
if ( resize_symmetric == 2 ) active_object->setPosition ( xo - dist, yo ) ;
|
|
break ;
|
|
|
|
case 5 : // Resizing on y-max
|
|
dist = y - yo - h ;
|
|
if (h + dist < 5) break ;
|
|
if ( resize_symmetric * dist < -h ) dist = 1 - h / resize_symmetric ;
|
|
active_object->setSize ( w, h + resize_symmetric * dist ) ;
|
|
if ( resize_symmetric == 2 ) active_object->setPosition ( xo, yo - dist ) ;
|
|
break ;
|
|
|
|
case 6 : // Resizing bottom-left
|
|
if ( yo - y > xo - x )
|
|
dist = yo - y;
|
|
else
|
|
dist = xo - x;
|
|
if ( (w + dist < 5) || (h + dist < 5) ) break ;
|
|
active_object->setPosition ( xo - dist, yo - dist ) ;
|
|
active_object->setSize ( w + dist, h + dist ) ;
|
|
break ;
|
|
|
|
case 7 : // Resizing top-right
|
|
if (y-yo-h>x-xo-w)
|
|
dist = y - yo - h ;
|
|
else
|
|
dist = x - xo - w ;
|
|
if ( (w + dist < 5) || (h + dist < 5) ) break ;
|
|
active_object->setSize ( w + dist, h + dist ) ;
|
|
break ;
|
|
|
|
case 8 : // Resizing top-left
|
|
if (y-yo-h>x-xo-w)
|
|
dist = y - yo - h ;
|
|
else
|
|
dist = xo - x ;
|
|
if ( (w + dist < 5) || (h + dist < 5) ) break ;
|
|
active_object->setPosition ( xo - dist, yo ) ;
|
|
active_object->setSize ( w + dist, h + dist ) ;
|
|
break ;
|
|
|
|
case 9 : // Resizing bottom-right
|
|
if (y-yo-h>x-xo-w)
|
|
dist = yo - y ;
|
|
else
|
|
dist = x - xo - w ;
|
|
if ( (w + dist < 5) || (h + dist < 5) ) break ;
|
|
active_object->setPosition ( xo , yo - dist ) ;
|
|
active_object->setSize ( w + dist, h + dist ) ;
|
|
break ;
|
|
}
|
|
|
|
int a, b ;
|
|
active_object->getPosition ( &a, &b ) ;
|
|
object_position_x->setValue ( a ) ;
|
|
object_position_y->setValue ( b ) ;
|
|
|
|
active_object->getSize ( &a, &b ) ;
|
|
object_size_x->setValue ( a ) ;
|
|
object_size_y->setValue ( b ) ;
|
|
}
|
|
}
|
|
wid = wid->next ;
|
|
}
|
|
}
|
|
glutPostRedisplay () ;
|
|
}
|
|
|
|
static void main_window_passivefn ( int x, int yy )
|
|
{
|
|
int y = main_window_height - yy ;
|
|
|
|
// Dragging the mouse without a button down: save the mouse coordinates
|
|
mouse_x = x ;
|
|
mouse_y = y ;
|
|
/*if (context_menu->isVisible() == 1)
|
|
{
|
|
puBox *cont_box = context_menu->getABox();
|
|
if ( ( x >= cont_box->min[0] ) && ( x <= cont_box->max[0] ) &&
|
|
( y >= cont_box->min[1] ) && ( y <= cont_box->max[1] ) )
|
|
{
|
|
context_menu->checkHit(-1, 0, mouse_x, mouse_y);
|
|
}
|
|
}*/
|
|
}
|
|
|
|
static void main_window_mousefn ( int button, int updown, int x, int yy )
|
|
{
|
|
int y = main_window_height - yy ;
|
|
|
|
mouse_x = x ;
|
|
mouse_y = y ;
|
|
|
|
if ( updown == PU_DOWN )
|
|
pguide_last_buttons |= ( 1 << button ) ;
|
|
else
|
|
pguide_last_buttons &= ~( 1 << button ) ;
|
|
|
|
if ( button == PU_RIGHT_BUTTON )
|
|
{
|
|
/* Pressed the right mouse button -- popup the manipulation window. */
|
|
WidgetList *wid = widgets ;
|
|
while ( wid )
|
|
{
|
|
puBox *box = wid->obj->getABox () ;
|
|
if ( wid->visible && ( x >= box->min[0] ) && ( x <= box->max[0] ) &&
|
|
( y >= box->min[1] ) && ( y <= box->max[1] ) )
|
|
{
|
|
|
|
active_widget = wid ;
|
|
active_object = wid->obj ;
|
|
/* We can modify mouse_x and mouse_y, because theyre not used again if we're in the right mouse function */
|
|
/* If we're real close to the right of the screen, modify the X position ...*/
|
|
if (mouse_x > main_window_width - 110 ) mouse_x = main_window_width - 110 ;
|
|
/* If we're real close to the top of the screen, modify the Y position...*/
|
|
if (mouse_y > main_window_height - 140) mouse_y = main_window_height - 140 ;
|
|
|
|
context_menu->setPosition(mouse_x, mouse_y) ;
|
|
context_menu->reveal() ;
|
|
//puSetActiveWidget(context_menu, mouse_x, mouse_y) ;
|
|
break ;
|
|
}
|
|
wid = wid->next ;
|
|
}
|
|
|
|
} else {
|
|
if ( puActiveWidget() && ( active_object != puActiveWidget() ) )
|
|
{
|
|
puActiveWidget() -> invokeDownCallback () ;
|
|
puDeactivateWidget () ;
|
|
}
|
|
|
|
ctrl_key_down = ( glutGetModifiers () & GLUT_ACTIVE_CTRL ) ;
|
|
|
|
if ( ( context_menu->isVisible() == 1) && ( active_widget ) )
|
|
{
|
|
puBox *cont_box = context_menu->getABox();
|
|
if ( ( x >= cont_box->min[0] ) && ( x <= cont_box->max[0] ) &&
|
|
( y >= cont_box->min[1] ) && ( y <= cont_box->max[1] ) )
|
|
{
|
|
context_menu->checkHit(button, updown, mouse_x, mouse_y);
|
|
} else {
|
|
context_menu->hide();
|
|
}
|
|
} else /*if ( context_menu->isVisible() == 1) { context_menu->hide(); } * The user did something funny, so hide the menu since they've been naughty */
|
|
{
|
|
// Downclick: Place a new widget, activate an existing widget, deactivate widget, or select from menu.
|
|
if ( updown == GLUT_DOWN )
|
|
{
|
|
// If there is a selected object, create a new one of that type.
|
|
// extern puObject *createWidget ( int type ) ;
|
|
extern int selected_object_type ;
|
|
|
|
if ( selected_object_type )
|
|
{
|
|
extern bool selected_object_sticky ;
|
|
extern char *selected_type_string ;
|
|
extern puButton *active_button ;
|
|
|
|
main_window_changed = true ;
|
|
|
|
// puObject *new_obj = createWidget ( selected_object->getType () ) ;
|
|
puObject *new_obj = new puFrame ( 0, 0, 90, 20 ) ;
|
|
char *object_type_name = new char [ PUSTRING_MAX ] ;
|
|
strcpy ( object_type_name, selected_type_string ) ;
|
|
new_obj->setLegend ( object_type_name ) ;
|
|
|
|
// Add the new object to the list of widgets
|
|
WidgetList *new_wid = new WidgetList ;
|
|
new_wid->obj = new_obj ;
|
|
new_wid->label_text = (char *)NULL ;
|
|
new_wid->legend_text = (char *)NULL ;
|
|
new_wid->allowed = (char *)NULL ;
|
|
new_wid->items = (char *)NULL ;
|
|
new_wid->object_type_name = object_type_name ;
|
|
new_wid->object_type = selected_object_type ;
|
|
new_wid->callbacks = 1 ; // Default: up callback enabled, others disabled
|
|
sprintf ( new_wid->object_name, "widget%d", widget_number++ ) ;
|
|
new_wid->visible = true ;
|
|
new_wid->locked = autolock ; /* Set it to the autolock var (true or false ) */
|
|
new_wid->layer = max_layer - 1 ;
|
|
new_wid->next = widgets ;
|
|
widgets = new_wid ;
|
|
|
|
// Set the new widget's position
|
|
new_obj->setPosition ( x, y ) ;
|
|
|
|
mouse_x_position_in_object = 0 ;
|
|
mouse_y_position_in_object = 0 ;
|
|
|
|
|
|
/* Set up the widget's default data values */
|
|
new_wid->intval1 = 0;
|
|
new_wid->intval2 = 0;
|
|
new_wid->boolval1 = false;
|
|
new_wid->boolval2 = false;
|
|
new_wid->boolval3 = false;
|
|
new_wid->floatval1 = 0.0f;
|
|
new_wid->floatval2 = 0.0f;
|
|
new_wid->floatval3 = 0.0f;
|
|
new_wid->floatval4 = 0.0f;
|
|
new_wid->floatval5 = 0.0f;
|
|
new_wid->floatval6 = 0.0f;
|
|
|
|
if (new_wid->object_type == PUCLASS_TEXT)
|
|
{
|
|
new_obj->setSize(5,20);
|
|
}
|
|
if (new_wid->object_type == PUCLASS_COMBOBOX)
|
|
{
|
|
new_wid->intval1 = 1;
|
|
new_wid->boolval1 = true;
|
|
}
|
|
|
|
if (new_wid->object_type == PUCLASS_SELECTBOX)
|
|
{
|
|
new_wid->intval1 = 1;
|
|
}
|
|
|
|
if (new_wid->object_type == PUCLASS_BUTTONBOX)
|
|
{
|
|
new_wid->boolval1 = true;
|
|
}
|
|
|
|
if (new_wid->object_type == PUCLASS_COMBOBOX)
|
|
{
|
|
new_wid->intval1 = 1;
|
|
new_wid->boolval1 = true;
|
|
}
|
|
|
|
if ( (new_wid->object_type == PUCLASS_SLIDER ) ||
|
|
(new_wid->object_type == PUCLASS_BISLIDER ) ||
|
|
(new_wid->object_type == PUCLASS_TRISLIDER ) ||
|
|
(new_wid->object_type == PUCLASS_DIAL ) ||
|
|
(new_wid->object_type == PUCLASS_SPINBOX ) ||
|
|
(new_wid->object_type == PUCLASS_SCROLLBAR ) )
|
|
{
|
|
new_wid->floatval1 = 1.0f;
|
|
new_wid->floatval2 = 0.0f;
|
|
new_wid->floatval3 = 0.0f;
|
|
new_wid->boolval1 = true;
|
|
}
|
|
|
|
if ( (new_wid->object_type == PUCLASS_SLIDER ) ||
|
|
(new_wid->object_type == PUCLASS_BISLIDER ) ||
|
|
(new_wid->object_type == PUCLASS_TRISLIDER ) )
|
|
{
|
|
new_wid->boolval2 = true;
|
|
}
|
|
|
|
if (new_wid->object_type == PUCLASS_SLIDER)
|
|
{
|
|
new_wid->floatval4 = 0.5f;
|
|
}
|
|
|
|
if (new_wid->object_type == PUCLASS_BISLIDER)
|
|
{
|
|
new_wid->floatval4 = 1.0f;
|
|
new_wid->floatval5 = 0.0f;
|
|
}
|
|
|
|
if (new_wid->object_type == PUCLASS_TRISLIDER)
|
|
{
|
|
new_wid->floatval4 = 1.0f;
|
|
new_wid->floatval5 = 0.0f;
|
|
new_wid->floatval6 = 0.5f;
|
|
new_wid->boolval3 = false;
|
|
}
|
|
|
|
if (new_wid->object_type == PUCLASS_DIAL)
|
|
{
|
|
new_obj->setSize(50,50);
|
|
new_wid->boolval2 = true;
|
|
}
|
|
|
|
if (new_wid->object_type == PUCLASS_SPINBOX)
|
|
{
|
|
new_wid->boolval2 = true;
|
|
new_wid->floatval4 = 0.5f;
|
|
}
|
|
|
|
if (new_wid->object_type == PUCLASS_SCROLLBAR)
|
|
{
|
|
/* Not Yet Implemented */
|
|
}
|
|
|
|
if (new_wid->object_type == PUCLASS_SPINBOX)
|
|
{
|
|
new_wid->boolval2 = true;
|
|
new_wid->floatval4 = 0.5f;
|
|
}
|
|
|
|
if (new_wid->object_type == PUCLASS_INPUT)
|
|
{
|
|
new_wid->boolval1 = true;
|
|
}
|
|
|
|
if (new_wid->object_type == PUCLASS_LARGEINPUT)
|
|
{
|
|
new_wid->boolval1 = true;
|
|
new_wid->intval1 = 1;
|
|
new_wid->intval2 = 5;
|
|
}
|
|
|
|
if (new_wid->object_type == PUCLASS_MENUBAR)
|
|
{
|
|
new_obj->setSize( 120, 30) ;
|
|
new_obj->setPosition( 0, puGetWindowHeight()-30) ;
|
|
new_wid->locked = true ;
|
|
}
|
|
|
|
if (new_wid->object_type == PUCLASS_VERTMENU)
|
|
{
|
|
new_obj->setSize( 45, 120) ;
|
|
new_obj->setPosition( 0, puGetWindowHeight()-120) ;
|
|
new_obj->setLegend("");
|
|
new_obj->setLabelPlace(PUPLACE_BOTTOM_LEFT);
|
|
new_obj->setLabel("puVerticalMenu");
|
|
new_wid->locked = true ;
|
|
}
|
|
|
|
// Make the new widget the active widget
|
|
active_object = new_obj ;
|
|
active_widget = new_wid ;
|
|
|
|
// If the "sticky" flag is not set, reset the selected object
|
|
if ( !selected_object_sticky )
|
|
{
|
|
selected_object_type = 0 ;
|
|
active_button->setValue ( 0 ) ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Clicking on a widget in the main widget list activates it
|
|
WidgetList *wid = widgets ;
|
|
while ( wid )
|
|
{
|
|
puBox *box = wid->obj->getABox () ;
|
|
if ( wid->visible && ( x >= box->min[0] ) && ( x <= box->max[0] ) &&
|
|
( y >= box->min[1] ) && ( y <= box->max[1] ) )
|
|
{
|
|
active_widget = wid ;
|
|
active_object = wid->obj ;
|
|
if ( abs ( x - box->min[0] ) < RESIZING_BORDER_WIDTH )
|
|
activity_flag = 2 ; // Resizing on x-min
|
|
else if ( abs ( x - box->max[0] ) < RESIZING_BORDER_WIDTH )
|
|
activity_flag = 4 ; // Resizing on x-max
|
|
else if ( abs ( y - box->min[1] ) < RESIZING_BORDER_WIDTH )
|
|
activity_flag = 3 ; // Resizing on y-min
|
|
else if ( abs ( y - box->max[1] ) < RESIZING_BORDER_WIDTH )
|
|
activity_flag = 5 ; // Resizing on y-max
|
|
else
|
|
activity_flag = 1 ; // Away from edges, we're moving it
|
|
|
|
/* Now we check and see if we're clicking on a corner - the sensitivity for
|
|
the determiniation of whether we're clicking a corner or not is held by the
|
|
definition of "RESIZING_CORNER_BORDER_WIDTH" which is at the top of this file */
|
|
|
|
int corner_resize_width = RESIZING_CORNER_BORDER_WIDTH + (((box->max[0] - box->min[0]) + (box->max[1] - box->min[1]) / 2 ) / 50 ) * 2 ;
|
|
|
|
if ( activity_flag != 1 )
|
|
{
|
|
// Bottom Right Corner
|
|
if ( ( abs( y - box->min[1] ) < corner_resize_width ) && (abs ( x - box->max[0] ) < corner_resize_width ) )
|
|
activity_flag = 9;
|
|
|
|
// Bottom Left Corner
|
|
if ( ( abs( y - box->min[1] ) < corner_resize_width ) && (abs ( x - box->min[0] ) < corner_resize_width ) )
|
|
activity_flag = 6;
|
|
|
|
// Top Right Corner
|
|
if ( ( abs( y - box->max[1] ) < corner_resize_width ) && (abs ( x - box->max[0] ) < corner_resize_width ) )
|
|
activity_flag = 7;
|
|
|
|
// Top Left Corner
|
|
if ( ( abs( y - box->max[1] ) < corner_resize_width ) && (abs ( x - box->min[0] ) < corner_resize_width ) )
|
|
activity_flag = 8;
|
|
}
|
|
|
|
/* If CTRL is held down, symmetric resize is forced. */
|
|
|
|
resize_symmetric = ctrl_key_down ? 2 : 1 ;
|
|
|
|
if (active_widget->object_type == PUCLASS_DIAL)
|
|
resize_corner = 1 ;
|
|
else
|
|
resize_corner = 0;
|
|
|
|
int object_x, object_y ;
|
|
active_object->getPosition ( &object_x, &object_y ) ;
|
|
mouse_x_position_in_object = x - object_x ;
|
|
mouse_y_position_in_object = y - object_y ;
|
|
|
|
break ;
|
|
}
|
|
|
|
wid = wid->next ;
|
|
}
|
|
|
|
if ( ( !wid ) && ( context_menu->isVisible()==0 ) ) // Ran through the entire list, deactivate any active widget
|
|
{
|
|
active_widget = (WidgetList *)NULL ;
|
|
active_object = (puObject *)NULL ;
|
|
}
|
|
}
|
|
}
|
|
|
|
setStatusWidgets ( active_widget ) ;
|
|
}
|
|
}
|
|
glutPostRedisplay () ;
|
|
}
|
|
|
|
|
|
static void main_window_reshapefn ( int w, int h )
|
|
{
|
|
extern puInput *window_size_x ;
|
|
extern puInput *window_size_y ;
|
|
|
|
if (done_first_setup)
|
|
main_window_changed = true ;
|
|
else
|
|
done_first_setup = true ;
|
|
|
|
if ( ( !currently_loading ) && (
|
|
( mouse_x < main_window_width/2 ) || // Grabbed the left edge ...
|
|
( mouse_y < main_window_height/2 ) ) ) // or the bottom edge, move the widgets
|
|
{
|
|
WidgetList *wid = widgets ;
|
|
int deltax = 0 ;
|
|
int deltay = 0 ;
|
|
|
|
if ( mouse_x < main_window_width/2 ) deltax = w - main_window_width ;
|
|
if ( mouse_y < main_window_height/2 ) deltay = h - main_window_height ;
|
|
|
|
while ( wid )
|
|
{
|
|
int x, y ;
|
|
wid->obj->getPosition ( &x, &y ) ;
|
|
wid->obj->setPosition ( x + deltax, y + deltay ) ;
|
|
|
|
wid = wid->next ;
|
|
}
|
|
}
|
|
|
|
main_window_width = w ;
|
|
main_window_height = h ;
|
|
|
|
window_size_x->setValue ( w ) ;
|
|
window_size_y->setValue ( h ) ;
|
|
|
|
currently_loading = false ;
|
|
}
|
|
|
|
static void main_window_displayfn ( void )
|
|
{
|
|
/* Clear the screen */
|
|
glutSetWindow ( main_window ) ;
|
|
|
|
glClearColor ( main_window_color_r, main_window_color_g, main_window_color_b, main_window_color_a ) ;
|
|
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
|
|
|
|
// Set the OpenGL to draw PUI widgets
|
|
|
|
int w = puGetWindowWidth () ;
|
|
int h = puGetWindowHeight () ;
|
|
|
|
glPushAttrib ( GL_ENABLE_BIT | GL_TRANSFORM_BIT | GL_LIGHTING_BIT ) ;
|
|
|
|
glDisable ( GL_LIGHTING ) ;
|
|
glDisable ( GL_FOG ) ;
|
|
glDisable ( GL_TEXTURE_2D ) ;
|
|
glDisable ( GL_DEPTH_TEST ) ;
|
|
glDisable ( GL_CULL_FACE ) ;
|
|
|
|
glViewport ( 0, 0, w, h ) ;
|
|
|
|
glMatrixMode ( GL_PROJECTION ) ;
|
|
glPushMatrix () ;
|
|
glLoadIdentity () ;
|
|
gluOrtho2D ( 0, w, 0, h ) ;
|
|
glMatrixMode ( GL_MODELVIEW ) ;
|
|
glPushMatrix () ;
|
|
glLoadIdentity () ;
|
|
|
|
// Draw the widgets
|
|
int layer ;
|
|
for ( layer = 0; layer < max_layer; layer++ )
|
|
{
|
|
WidgetList *wid = widgets ;
|
|
while ( wid )
|
|
{
|
|
if ( wid->visible && ( wid->layer == layer ) ) wid->obj->draw ( 0, 0 ) ;
|
|
wid = wid->next ;
|
|
}
|
|
}
|
|
|
|
if ( active_object )
|
|
{
|
|
puBox *box = active_object->getBBox () ;
|
|
glColor4f ( 0.0f, 0.0f, 0.0f, 1.0f ) ;
|
|
glLineWidth ( 3.0f ) ;
|
|
glBegin ( GL_LINES ) ;
|
|
glVertex2i ( box->min[0]-1, box->min[1]-1 ) ;
|
|
glVertex2i ( box->max[0]+1, box->min[1]-1 ) ;
|
|
glVertex2i ( box->max[0]+1, box->max[1]+1 ) ;
|
|
glVertex2i ( box->min[0]-1, box->max[1]+1 ) ;
|
|
glVertex2i ( box->min[0]-1, box->min[1]-1 ) ;
|
|
glEnd () ;
|
|
}
|
|
|
|
context_menu->draw(0,0);
|
|
|
|
/* Update GLUT */
|
|
|
|
glutSwapBuffers () ;
|
|
glutPostRedisplay () ;
|
|
|
|
}
|
|
|
|
int main ( int argc, char **argv )
|
|
{
|
|
extern int define_widget_window () ;
|
|
extern int define_status_window () ;
|
|
int i = 0;
|
|
|
|
strcpy ( main_window_name, "PUI GUI Builder" ) ;
|
|
|
|
glutInitWindowPosition( 100, 0 ) ;
|
|
glutInitWindowSize ( main_window_width, main_window_height ) ;
|
|
glutInit ( &argc, argv ) ;
|
|
glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ;
|
|
main_window = glutCreateWindow ( main_window_name ) ;
|
|
glutDisplayFunc ( main_window_displayfn ) ;
|
|
glutKeyboardFunc ( main_window_keyfn ) ;
|
|
glutSpecialFunc ( main_window_specialfn ) ;
|
|
glutMouseFunc ( main_window_mousefn ) ;
|
|
glutMotionFunc ( main_window_motionfn ) ;
|
|
glutPassiveMotionFunc ( main_window_passivefn ) ;
|
|
glutReshapeFunc ( main_window_reshapefn ) ;
|
|
glutIdleFunc ( main_window_displayfn ) ;
|
|
|
|
// If we're using windows, ignore the C: or whatnot
|
|
|
|
#ifdef WIN32
|
|
#define PATH_SEPARATOR '\\'
|
|
strcpy (pguide_current_directory, argv[0]+2);
|
|
#else
|
|
#define PATH_SEPARATOR '/'
|
|
strcpy (pguide_current_directory, argv[0]);
|
|
#endif
|
|
i = strlen(pguide_current_directory);
|
|
|
|
|
|
while (pguide_current_directory[i] != PATH_SEPARATOR) {
|
|
if (i>0) i-- ;
|
|
else break ;
|
|
}
|
|
pguide_current_directory[i+1] = '\0';
|
|
|
|
puInit () ;
|
|
|
|
#ifdef VOODOO
|
|
puShowCursor () ;
|
|
#endif
|
|
|
|
puSetDefaultStyle ( PUSTYLE_SMALL_SHADED ) ;
|
|
puSetDefaultColourScheme ( 0.8f, 0.8f, 0.8f, 1.0f ) ;
|
|
|
|
// Add the properties context menu
|
|
context_menu = new puPopupMenu( 0, 0 ) ;
|
|
context_menu->add_item("Properties", cb_edit_properties) ;
|
|
context_menu->add_item("Lock/Unlock", cb_lock_toggle) ;
|
|
context_menu->add_item("Delete", cb_popup_delete) ;
|
|
context_menu->add_item("Cut", NULL) ;
|
|
context_menu->add_item("Copy", NULL) ;
|
|
context_menu->add_item("Change Class", NULL) ;
|
|
context_menu->close() ;
|
|
|
|
// Set up the other windows
|
|
define_widget_window () ;
|
|
define_status_window () ;
|
|
|
|
glutMainLoop () ;
|
|
return 0 ;
|
|
}
|
|
|