Initial commit
This commit is contained in:
parent
015929c965
commit
7e8b9b5570
@ -15,7 +15,7 @@ AM_CPPFLAGS = -D _GNU_SOURCE -I.. -I$(srcdir)/src/libcm -I$(srcdir)/src/libcm/
|
|||||||
AM_CFLAGS = -Wno-multichar
|
AM_CFLAGS = -Wno-multichar
|
||||||
AM_CXXFLAGS =
|
AM_CXXFLAGS =
|
||||||
AM_LDFLAGS =
|
AM_LDFLAGS =
|
||||||
MYLIBS = -lpthread -lfftw3f -lfftw3
|
MYLIBS = -lpthread -lfftw3f -lfftw3 -lfltk
|
||||||
CMLIBS = src/libcm/libcm.la # autoconfig manual recommends storing direct referenes to non-3rd party libraries rather than using -L and -l
|
CMLIBS = src/libcm/libcm.la # autoconfig manual recommends storing direct referenes to non-3rd party libraries rather than using -L and -l
|
||||||
|
|
||||||
|
|
||||||
@ -56,6 +56,7 @@ include_HEADERS += $(cmHDR)
|
|||||||
lib_LTLIBRARIES += src/libcm/libcm.la
|
lib_LTLIBRARIES += src/libcm/libcm.la
|
||||||
|
|
||||||
|
|
||||||
src_proj_proj_SOURCES = src/proj/main.c
|
src_cmflapp_cmflapp_SOURCES = src/cmflapp/main.cpp src/cmflapp/app.h src/cmflapp/app.cpp
|
||||||
src_proj_proj_LDADD = $(CMLIBS) $(MYLIBS)
|
src_cmflapp_cmflapp_SOURCES += src/cmflapp/Fl_Splitter.h src/cmflapp/Fl_Splitter.cpp
|
||||||
bin_PROGRAMS += src/proj/proj
|
src_cmflapp_cmflapp_LDADD = $(CMLIBS) $(MYLIBS)
|
||||||
|
bin_PROGRAMS += src/cmflapp/cmflapp
|
||||||
|
@ -3,10 +3,10 @@
|
|||||||
# this configure.ac or any of the Makefile.am files.
|
# this configure.ac or any of the Makefile.am files.
|
||||||
#
|
#
|
||||||
|
|
||||||
AC_INIT([proj],[1.0],[proj@larke.org])
|
AC_INIT([cmflapp],[1.0],[cmflapp@larke.org])
|
||||||
AC_CONFIG_AUX_DIR([build-aux]) # put aux files in build-aux
|
AC_CONFIG_AUX_DIR([build-aux]) # put aux files in build-aux
|
||||||
AM_INIT_AUTOMAKE([1.9 -Wall foreign subdir-objects]) # subdir-objects needed for non-recursive make
|
AM_INIT_AUTOMAKE([1.9 -Wall foreign subdir-objects]) # subdir-objects needed for non-recursive make
|
||||||
AC_CONFIG_SRCDIR([src/proj/main.c])
|
AC_CONFIG_SRCDIR([src/cmflapp/main.cpp])
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
|
|
||||||
|
265
src/cmflapp/Fl_Splitter.cpp
Normal file
265
src/cmflapp/Fl_Splitter.cpp
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
// Code based on: http://www.mail-archive.com/fltk@easysw.com/msg04573.html
|
||||||
|
// Lucas Sanner/Ian MacArthur
|
||||||
|
|
||||||
|
#include "Fl_Splitter.h"
|
||||||
|
|
||||||
|
void Fl_HSplitter::draw()
|
||||||
|
{
|
||||||
|
Fl_Group::draw();
|
||||||
|
fl_color(FL_BLACK);
|
||||||
|
fl_line_style( FL_DOT, 1);
|
||||||
|
|
||||||
|
if(bSplit && Fl::event_button1() != 0)
|
||||||
|
{
|
||||||
|
fl_push_clip(x(), y(), w(), h());
|
||||||
|
|
||||||
|
yPos = Fl::event_y();
|
||||||
|
|
||||||
|
if(Fl::event_y() > h() - (border * 2))
|
||||||
|
yPos = h() - (border * 2);
|
||||||
|
|
||||||
|
if(Fl::event_y() < y() + (border * 2))
|
||||||
|
yPos = y() + (border * 2);
|
||||||
|
|
||||||
|
fl_line( x() + border, yPos - 1, x() + w() - (border*2), yPos - 1 );
|
||||||
|
fl_line( x() + border, yPos , x() + w() - (border*2), yPos );
|
||||||
|
fl_line( x() + border, yPos + 1, x() + w() - (border*2), yPos + 1 );
|
||||||
|
|
||||||
|
/*
|
||||||
|
fl_line(
|
||||||
|
x() + border,
|
||||||
|
yPos,
|
||||||
|
x() + w() - (border*2),
|
||||||
|
yPos );
|
||||||
|
|
||||||
|
fl_line(
|
||||||
|
x() + border,
|
||||||
|
yPos + 1,
|
||||||
|
x() + w() - (border*2),
|
||||||
|
yPos + 1 );
|
||||||
|
*/
|
||||||
|
|
||||||
|
fl_pop_clip();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fl_push_clip(x(), y(), w(), h());
|
||||||
|
fl_pop_clip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Fl_HSplitter::handle(int e)
|
||||||
|
{
|
||||||
|
int ret = Fl_Group::handle(e);
|
||||||
|
|
||||||
|
switch(e)
|
||||||
|
{
|
||||||
|
case FL_MOVE:
|
||||||
|
|
||||||
|
if(Fl::event_y() > hCtnl - border && Fl::event_y() < hCtnl + border)
|
||||||
|
{
|
||||||
|
fl_cursor(FL_CURSOR_NS);
|
||||||
|
bSplit = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fl_cursor(FL_CURSOR_DEFAULT);
|
||||||
|
bSplit = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case FL_PUSH:
|
||||||
|
|
||||||
|
if(Fl::event_button() == FL_LEFT_MOUSE && bSplit)
|
||||||
|
{
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case FL_RELEASE:
|
||||||
|
|
||||||
|
if(Fl::event_button() == FL_LEFT_MOUSE && bSplit)
|
||||||
|
{
|
||||||
|
container1->resize(x(), y(), w(), yPos - y());
|
||||||
|
hCtnl = yPos;
|
||||||
|
container2->resize(x(),hCtnl, w(), h() - (yPos - y()));
|
||||||
|
|
||||||
|
if( stretchTopFl )
|
||||||
|
init_sizes();
|
||||||
|
|
||||||
|
bSplit = false;
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case FL_DRAG:
|
||||||
|
|
||||||
|
if(bSplit && Fl::event_state(FL_BUTTON1) != 0)
|
||||||
|
redraw();
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Fl_HSplitter::Fl_HSplitter(int x, int y, int w, int h, int h1, const char *l, bool stretchBotFl)
|
||||||
|
: Fl_Group(x, y, w, h, l)
|
||||||
|
{
|
||||||
|
int h2 = h - h1;
|
||||||
|
|
||||||
|
begin();
|
||||||
|
container1 = new Splitter_Container(x, y, w, h1);
|
||||||
|
//container1->color((Fl_Color) FL_RED);
|
||||||
|
end();
|
||||||
|
|
||||||
|
begin();
|
||||||
|
container2 = new Splitter_Container(x, y + h1, w, h2);
|
||||||
|
//container2->color((Fl_Color) FL_BLUE);
|
||||||
|
end();
|
||||||
|
|
||||||
|
hCtnl = y + h1;
|
||||||
|
bSplit = false;
|
||||||
|
stretchTopFl = !stretchBotFl;
|
||||||
|
|
||||||
|
border = Fl::box_dy(FL_DOWN_BOX);
|
||||||
|
|
||||||
|
if( stretchTopFl )
|
||||||
|
resizable(container1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Fl_HSplitter::resize_splitter(int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
resize(x, y, w, h);
|
||||||
|
|
||||||
|
if( stretchTopFl )
|
||||||
|
{
|
||||||
|
hCtnl = container1->h() + y;
|
||||||
|
yPos = hCtnl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
container1->resize(x, y, w, hCtnl - y);
|
||||||
|
container2->resize(x, hCtnl, w, h - (hCtnl - y));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Fl_VSplitter::draw()
|
||||||
|
{
|
||||||
|
Fl_Group::draw();
|
||||||
|
fl_color(FL_BLACK);
|
||||||
|
fl_line_style( FL_DOT, 1);
|
||||||
|
|
||||||
|
if(bSplit && Fl::event_button1() != 0)
|
||||||
|
{
|
||||||
|
fl_push_clip(x(), y(), w(), h());
|
||||||
|
|
||||||
|
xPos = Fl::event_x();
|
||||||
|
|
||||||
|
if(Fl::event_x() > w() - (border * 2))
|
||||||
|
xPos = w() - (border * 2);
|
||||||
|
|
||||||
|
if(Fl::event_x() < x() + (border * 2))
|
||||||
|
xPos = x() + (border * 2);
|
||||||
|
|
||||||
|
fl_line(xPos - 1, y() + border, xPos - 1, y() + h() - (border * 2));
|
||||||
|
fl_line(xPos, y() + border, xPos, y() + h() - (border * 2));
|
||||||
|
fl_line(xPos + 1, y() + border, xPos + 1, y() + h() - (border * 2));
|
||||||
|
|
||||||
|
fl_pop_clip();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fl_push_clip(x(), y(), w(), h());
|
||||||
|
fl_pop_clip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Fl_VSplitter::handle(int e)
|
||||||
|
{
|
||||||
|
int ret = Fl_Group::handle(e);
|
||||||
|
|
||||||
|
switch(e)
|
||||||
|
{
|
||||||
|
case FL_MOVE:
|
||||||
|
|
||||||
|
if(Fl::event_x() > wCtn1 - border && Fl::event_x() < wCtn1 + border)
|
||||||
|
{
|
||||||
|
fl_cursor(FL_CURSOR_WE);
|
||||||
|
bSplit = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fl_cursor(FL_CURSOR_DEFAULT);
|
||||||
|
bSplit = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case FL_PUSH:
|
||||||
|
|
||||||
|
if(Fl::event_button() == FL_LEFT_MOUSE && bSplit)
|
||||||
|
{
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case FL_RELEASE:
|
||||||
|
|
||||||
|
if(Fl::event_button() == FL_LEFT_MOUSE && bSplit)
|
||||||
|
{
|
||||||
|
container1->resize(x(), y(), xPos, h());
|
||||||
|
wCtn1 = xPos;
|
||||||
|
container2->resize(wCtn1, y(), w() - wCtn1, h());
|
||||||
|
bSplit = false;
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case FL_DRAG:
|
||||||
|
|
||||||
|
if(bSplit && Fl::event_state(FL_BUTTON1) != 0)
|
||||||
|
redraw();
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
Fl_VSplitter::Fl_VSplitter(int x, int y, int w, int h, const char *l)
|
||||||
|
: Fl_Group(x, y, w, h, l)
|
||||||
|
{
|
||||||
|
begin();
|
||||||
|
container1 = new Splitter_Container(x, y, w / 2, h);
|
||||||
|
//container1->color((Fl_Color) FL_RED);
|
||||||
|
end();
|
||||||
|
|
||||||
|
begin();
|
||||||
|
container2 = new Splitter_Container(x + (w / 2), y, w / 2, h);
|
||||||
|
//container2->color((Fl_Color) FL_BLUE);
|
||||||
|
end();
|
||||||
|
|
||||||
|
wCtn1 = w / 2;
|
||||||
|
bSplit = false;
|
||||||
|
|
||||||
|
border = Fl::box_dx(FL_DOWN_BOX);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Fl_VSplitter::resize_splitter(int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
resize(x, y, w, h);
|
||||||
|
container1->resize(x, y, wCtn1, h);
|
||||||
|
container2->resize(wCtn1, y, w - wCtn1, h);
|
||||||
|
}
|
||||||
|
|
74
src/cmflapp/Fl_Splitter.h
Normal file
74
src/cmflapp/Fl_Splitter.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
// Code based on: http://www.mail-archive.com/fltk@easysw.com/msg04573.html
|
||||||
|
// Lucas Sanner/Ian MacArthur
|
||||||
|
|
||||||
|
#ifndef Fl_Splitter_h
|
||||||
|
#define Fl_Splitter_h
|
||||||
|
|
||||||
|
#include <FL/Fl.H>
|
||||||
|
#include <FL/Fl_Group.H>
|
||||||
|
#include <FL/Fl_Box.H>
|
||||||
|
#include <FL/fl_draw.H>
|
||||||
|
|
||||||
|
|
||||||
|
class Splitter_Container : public Fl_Group
|
||||||
|
{
|
||||||
|
void draw()
|
||||||
|
{
|
||||||
|
fl_push_clip(x(), y(), w(), h());
|
||||||
|
Fl_Group::draw();
|
||||||
|
fl_pop_clip();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Splitter_Container(int x, int y, int w, int h, char *l = NULL)
|
||||||
|
: Fl_Group(x, y, w, h, l)
|
||||||
|
{
|
||||||
|
//box(FL_DOWN_BOX);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Fl_HSplitter : public Fl_Group
|
||||||
|
{
|
||||||
|
int hCtnl, border, yPos;
|
||||||
|
bool bSplit;
|
||||||
|
bool stretchTopFl; // set to make top container stretch when splitter is resized
|
||||||
|
int hh2;
|
||||||
|
|
||||||
|
void draw();
|
||||||
|
|
||||||
|
int handle(int e);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Splitter_Container *container1, *container2;
|
||||||
|
|
||||||
|
Fl_HSplitter(int x, int y, int w, int h, int h1, const char *l=NULL, bool stretchBotFl=false);
|
||||||
|
|
||||||
|
void resize_splitter(int x, int y, int w, int h);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Fl_VSplitter : public Fl_Group
|
||||||
|
{
|
||||||
|
|
||||||
|
int wCtn1, border, xPos;
|
||||||
|
bool bSplit;
|
||||||
|
|
||||||
|
void draw();
|
||||||
|
int handle(int e);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Splitter_Container *container1, *container2;
|
||||||
|
|
||||||
|
Fl_VSplitter(int x, int y, int w, int h, const char *l = NULL);
|
||||||
|
|
||||||
|
void resize_splitter(int x, int y, int w, int h);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
555
src/cmflapp/app.cpp
Normal file
555
src/cmflapp/app.cpp
Normal file
@ -0,0 +1,555 @@
|
|||||||
|
#include <FL/Fl.H>
|
||||||
|
#include <FL/Fl_Widget.H>
|
||||||
|
#include <FL/Fl_Double_Window.H>
|
||||||
|
#include <FL/Fl_Text_Buffer.H>
|
||||||
|
#include <FL/Fl_Text_Display.H>
|
||||||
|
#include <FL/Fl_Tabs.H>
|
||||||
|
#include <FL/Fl_Menu_Item.H>
|
||||||
|
#include <FL/Fl_Menu_Bar.H>
|
||||||
|
#include <FL/Fl_Button.H>
|
||||||
|
#include <FL/Fl_Check_Button.H>
|
||||||
|
#include <FL/Fl_Menu_Button.H>
|
||||||
|
#include <FL/Fl_Value_Input.H>
|
||||||
|
#include <FL/Fl_Value_Slider.H>
|
||||||
|
#include <FL/Fl_Input.H>
|
||||||
|
#include <FL/Fl_Box.H>
|
||||||
|
#include <FL/Fl_File_Chooser.H>
|
||||||
|
#include <FL/fl_draw.H>
|
||||||
|
|
||||||
|
#include "Fl_Splitter.h"
|
||||||
|
|
||||||
|
#include "cmPrefix.h"
|
||||||
|
#include "cmGlobal.h"
|
||||||
|
#include "cmRpt.h"
|
||||||
|
#include "cmErr.h"
|
||||||
|
#include "cmCtx.h"
|
||||||
|
#include "cmMem.h"
|
||||||
|
#include "cmMallocDebug.h"
|
||||||
|
#include "cmFileSys.h"
|
||||||
|
#include "cmThread.h"
|
||||||
|
|
||||||
|
#include "appErr.h"
|
||||||
|
#include "app.h"
|
||||||
|
|
||||||
|
class drawWnd : public Fl_Widget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
drawWnd(app* ap, int x, int y, int w, int h, const char* label = NULL );
|
||||||
|
virtual ~drawWnd();
|
||||||
|
|
||||||
|
virtual int handle(int event);
|
||||||
|
virtual void resize(int x, int y, int w, int h );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void draw();
|
||||||
|
|
||||||
|
private:
|
||||||
|
app* _app;
|
||||||
|
};
|
||||||
|
|
||||||
|
drawWnd::drawWnd(app* ap, int x, int y, int w, int h, const char* label )
|
||||||
|
: Fl_Widget(x,y,w,h,label),
|
||||||
|
_app(ap)
|
||||||
|
{}
|
||||||
|
|
||||||
|
drawWnd::~drawWnd()
|
||||||
|
{}
|
||||||
|
|
||||||
|
int drawWnd::handle(int event)
|
||||||
|
{
|
||||||
|
switch(event)
|
||||||
|
{
|
||||||
|
case FL_PUSH:
|
||||||
|
{
|
||||||
|
const char* label;
|
||||||
|
switch( Fl::event_button() )
|
||||||
|
{
|
||||||
|
case FL_LEFT_MOUSE: label = "left"; break;
|
||||||
|
case FL_RIGHT_MOUSE: label = "right"; break;
|
||||||
|
case FL_MIDDLE_MOUSE: label = "middle"; break;
|
||||||
|
default:
|
||||||
|
label = "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
_app->print("%i %i %s\n",Fl::event_x(),Fl::event_y(),label);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return Fl_Widget::handle(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawWnd::resize(int x, int y, int w, int h )
|
||||||
|
{
|
||||||
|
// must call base to make size change
|
||||||
|
Fl_Widget::resize(x,y,w,h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawWnd::draw()
|
||||||
|
{
|
||||||
|
int offs = 10;
|
||||||
|
//fl_draw_box(FL_DOWN_BOX,x()+10,y()+10,w()-20,h()-20,FL_RED);
|
||||||
|
//fl_frame("XXXX",x()+offs,y()+offs,w()-2*offs,h()-2*offs);
|
||||||
|
fl_line_style(FL_SOLID,1,NULL);
|
||||||
|
fl_color(FL_RED);
|
||||||
|
fl_line(x()+offs,y()+offs,x()+w()-offs,y()+h()-offs);
|
||||||
|
|
||||||
|
|
||||||
|
int x = w()/2;
|
||||||
|
int y = h()/2;
|
||||||
|
|
||||||
|
fl_color(FL_BLACK);
|
||||||
|
fl_draw(90,"string",x,y);
|
||||||
|
|
||||||
|
// XXXXXXX
|
||||||
|
// X00000X
|
||||||
|
// X00000X
|
||||||
|
// X00X00X
|
||||||
|
// X00000X
|
||||||
|
// X00000X
|
||||||
|
// XXXXXXX
|
||||||
|
|
||||||
|
fl_rect(x-3,y-3,7,7);
|
||||||
|
fl_point(x,y);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
app::app(cmCtx_t* ctx, cmTsMp1cH_t printqH, int w, int h, const char* label, int argc, char* argv[])
|
||||||
|
: Fl_Double_Window(w,h,label), _timerPeriodSecs(0),
|
||||||
|
_ctx(ctx), _splt(NULL),_buf(NULL),_con(NULL),_tabs(NULL),_menu(NULL),
|
||||||
|
_printqH(printqH),_printFl(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
// install a callback to cleanup when the app window closes
|
||||||
|
// (the btn and menu callbacks also rely on a pointer to 'this' being found in app.user_data()
|
||||||
|
// see _getApp())
|
||||||
|
callback(_s_callback,this);
|
||||||
|
|
||||||
|
// the main window is divided between the menu bar on top
|
||||||
|
// and a horizontal splitter on the bottom
|
||||||
|
begin();
|
||||||
|
createMenu(w,kMenuH);
|
||||||
|
_splt = new Fl_HSplitter(0, kMenuH, w, h-kStatusH, h-kStatusH-100);
|
||||||
|
end();
|
||||||
|
|
||||||
|
// Create a text display object for console output and
|
||||||
|
// add it to the lower splitter area
|
||||||
|
_buf = new Fl_Text_Buffer();
|
||||||
|
_con = new Fl_Text_Display(_splt->container2->x(),_splt->container2->y(),_splt->container2->w(),_splt->container2->h());
|
||||||
|
_con->buffer(_buf);
|
||||||
|
_splt->container2->add(_con);
|
||||||
|
|
||||||
|
// create tabbed windows
|
||||||
|
const char* titles[] = { "Title 1", "Title 2" };
|
||||||
|
_create_tabs(2,titles);
|
||||||
|
|
||||||
|
// make the splitter the resizable group element (thereby making the menu non-resizable).
|
||||||
|
// see:http://fltk.org/articles.php?L415+I0+T+M1000+P1
|
||||||
|
resizable(_splt);
|
||||||
|
show(argc, argv);
|
||||||
|
|
||||||
|
// The application is now visible.
|
||||||
|
// direct all output to the console window
|
||||||
|
cmRptSetup(&_ctx->rpt,_s_print,_s_print, this);
|
||||||
|
cmTsMp1cSetCbFunc(_printqH, _s_print_queue_cb, this );
|
||||||
|
|
||||||
|
|
||||||
|
// install a timer
|
||||||
|
_timerPeriodSecs = 0.1;
|
||||||
|
Fl::add_timeout(_timerPeriodSecs,app::_s_timer_cb,this);
|
||||||
|
|
||||||
|
// install an idle callback
|
||||||
|
//Fl::add_idle(_s_idle_cb,this);
|
||||||
|
|
||||||
|
print("Started!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
app::~app()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void app::createControls(Fl_Group* grp)
|
||||||
|
{
|
||||||
|
const int vBord = 3;
|
||||||
|
const int ctl_width = 100;
|
||||||
|
int xx = grp->x() + 5;
|
||||||
|
int yy = grp->y() + vBord;
|
||||||
|
|
||||||
|
Fl_Check_Button* cbt = new Fl_Check_Button(xx,yy,ctl_width,kCtlH,"Check");
|
||||||
|
cbt->callback( _s_btn_cb, kBtn1MId );
|
||||||
|
yy += cbt->h() + vBord;
|
||||||
|
|
||||||
|
Fl_Button* btn = new Fl_Button(xx,yy,ctl_width,kCtlH,"Button");
|
||||||
|
btn->callback( _s_btn_cb, kBtn2MId );
|
||||||
|
yy += btn->h() + vBord;
|
||||||
|
|
||||||
|
// menu buttons callback through menuCallback() not btnCallback()
|
||||||
|
Fl_Menu_Button* mbt = new Fl_Menu_Button(xx,yy,ctl_width,kCtlH,"Menu");
|
||||||
|
|
||||||
|
mbt->add("Item 1",0,_s_menu_btn_cb, (void*)kMenuBtn1MId, 0);
|
||||||
|
mbt->add("Item 2",0,_s_menu_btn_cb, (void*)kMenuBtn2MId, 0);
|
||||||
|
yy += mbt->h() + vBord;
|
||||||
|
|
||||||
|
Fl_Value_Input* vip = new Fl_Value_Input(xx,yy,ctl_width/2,kCtlH,"Value In");
|
||||||
|
vip->callback(_s_value_cb, kValue1MId );
|
||||||
|
vip->align(FL_ALIGN_RIGHT); // place label to the right of the input ctl
|
||||||
|
// Only make the callback when the enter key is struck or the ctl loses focus and the value has changed.
|
||||||
|
// Removing this line causes the callback whenever the input changes.
|
||||||
|
vip->when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE );
|
||||||
|
vip->bounds(-10.0,10.0);
|
||||||
|
vip->step(0.1);
|
||||||
|
yy += vip->h() + vBord;
|
||||||
|
|
||||||
|
Fl_Value_Slider* sdp = new Fl_Value_Slider(xx,yy,ctl_width,kCtlH,"Slider");
|
||||||
|
sdp->callback(_s_value_cb, kValue2MId );
|
||||||
|
sdp->align(FL_ALIGN_RIGHT);
|
||||||
|
sdp->type(FL_HOR_NICE_SLIDER);
|
||||||
|
sdp->bounds(-10.0,10.0);
|
||||||
|
sdp->step(0.1);
|
||||||
|
yy += sdp->h() + vBord;
|
||||||
|
|
||||||
|
Fl_Input* inp = new Fl_Input(xx,yy,ctl_width/2,kCtlH,"Text");
|
||||||
|
inp->callback(_s_input_cb,kInput1MId);
|
||||||
|
inp->align(FL_ALIGN_RIGHT);
|
||||||
|
yy += inp->h() + vBord;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void app::initializeTab(int tabIndex, int x, int y, int w, int h, const char* label)
|
||||||
|
{
|
||||||
|
switch(tabIndex)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
Fl_Group* grp = new Fl_Group(x,y,w,h,label);
|
||||||
|
grp->begin();
|
||||||
|
createControls(grp);
|
||||||
|
grp->end();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
Fl_Group* grp = new Fl_Group(x,y,w,h,label);
|
||||||
|
grp->begin();
|
||||||
|
_draw = new drawWnd(this,x,y,w,h,NULL);
|
||||||
|
grp->end();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void app::createMenu(int w, int h)
|
||||||
|
{
|
||||||
|
Fl_Menu_Item items[] =
|
||||||
|
{
|
||||||
|
{ "&File", 0, 0, 0, FL_SUBMENU },
|
||||||
|
{ "&New File", FL_COMMAND + 'n', (Fl_Callback*)_s_menu_cb, (void*)kFileNewMId },
|
||||||
|
{ "&Open File", FL_COMMAND + 'o', (Fl_Callback*)_s_menu_cb, (void*)kFileOpenMId },
|
||||||
|
{ 0 },
|
||||||
|
{ "&Edit", 0, 0, 0, FL_SUBMENU },
|
||||||
|
{ "&Copy", FL_COMMAND + 'c', (Fl_Callback*)_s_menu_cb, (void*)kEditCopyMId },
|
||||||
|
{ "&Paste", FL_COMMAND + 'v', (Fl_Callback*)_s_menu_cb, (void*)kEditPasteMId },
|
||||||
|
{ 0 },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
_menu = new Fl_Menu_Bar(0,0,w,h);
|
||||||
|
_menu->copy(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
void app::menuCallback(const Fl_Menu_Item* mip, long int id)
|
||||||
|
{
|
||||||
|
switch(id)
|
||||||
|
{
|
||||||
|
case kFileOpenMId:
|
||||||
|
{
|
||||||
|
// file chooser demo
|
||||||
|
|
||||||
|
const char* pathStr = cmFsUserDir(); // make the default dir the user's home dir
|
||||||
|
const char patStr[] = "Text Files (*.txt)\tAudio Files (*.{wav,aif,aiff})"; // All Files (*.*) is append to this automatically
|
||||||
|
const char titleStr[] = "Select files";
|
||||||
|
|
||||||
|
Fl_File_Chooser fc = Fl_File_Chooser(pathStr,patStr,Fl_File_Chooser::MULTI,titleStr);
|
||||||
|
|
||||||
|
fc.preview(0); // default the previous option to 'off'.
|
||||||
|
fc.show(); // show the chooser
|
||||||
|
|
||||||
|
// make the chooser modal
|
||||||
|
while( fc.shown() )
|
||||||
|
Fl::wait();
|
||||||
|
|
||||||
|
// print the selected files
|
||||||
|
int i;
|
||||||
|
for(i=1; i<=fc.count(); ++i)
|
||||||
|
print("%i %s\n",i,cmStringNullGuard(fc.value(i)));
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
print("%i %s\n",id,mip->label());
|
||||||
|
}
|
||||||
|
|
||||||
|
void app::btnCallback(const Fl_Button* bp, int id )
|
||||||
|
{
|
||||||
|
print("%i %s %i\n",id,bp->label(),bp->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
void app::valueCallback(const Fl_Valuator* vp, int id )
|
||||||
|
{
|
||||||
|
print("%i %s %f\n",id,vp->label(),vp->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
void app::inputCallback(const Fl_Input* ip, int id )
|
||||||
|
{
|
||||||
|
print("%i %s %s\n",id,ip->label(),ip->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
void app::appCallback(Fl_Widget* wp)
|
||||||
|
{
|
||||||
|
switch( Fl::event() )
|
||||||
|
{
|
||||||
|
case FL_CLOSE:
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
int cc = _closeCnt;
|
||||||
|
|
||||||
|
// attempt to shut down the pgm
|
||||||
|
_closeCnt += finalizePgm() == false;
|
||||||
|
|
||||||
|
// the first time the pgm fails to shut down
|
||||||
|
// do not allow the pgm to close the main window
|
||||||
|
// this will give a chance for the error messages
|
||||||
|
// to be diplayed in the console - all successive
|
||||||
|
// times the return value from finalizePgm() is
|
||||||
|
|
||||||
|
// ignored and the program is terminated.
|
||||||
|
if( _closeCnt == 1 && cc==0)
|
||||||
|
{
|
||||||
|
// send a strong hint that a problem occurred on shutdown
|
||||||
|
// and prevent the app from receiving events that might cause it to
|
||||||
|
// crash
|
||||||
|
deactivate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// When all windows are windows are closed then the app.
|
||||||
|
// will close - so hiding the application window
|
||||||
|
// causes the program to close.
|
||||||
|
//
|
||||||
|
// Note that simply returning from this callback will
|
||||||
|
// prevent the application from closing. Because the existence
|
||||||
|
// of the callback alone is enough to disable default
|
||||||
|
// event handling.
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
bool app::idleCallback()
|
||||||
|
{ return true; }
|
||||||
|
|
||||||
|
|
||||||
|
bool app::timerCallback()
|
||||||
|
{
|
||||||
|
_checkPrintQueue();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void app::error( const char* fmt, ... )
|
||||||
|
{
|
||||||
|
va_list vl;
|
||||||
|
va_start(vl,fmt);
|
||||||
|
|
||||||
|
int bufCharCnt = 511;
|
||||||
|
char buf[bufCharCnt+1];
|
||||||
|
|
||||||
|
int n = vsnprintf(buf,bufCharCnt,fmt,vl);
|
||||||
|
|
||||||
|
if( n > 0 )
|
||||||
|
print("%s Error: %s\n",label(),buf);
|
||||||
|
|
||||||
|
va_end(vl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void app::vprint(const char* fmt, va_list vl )
|
||||||
|
{
|
||||||
|
int bufCharCnt = 511;
|
||||||
|
char buf[bufCharCnt+1];
|
||||||
|
|
||||||
|
int n = vsnprintf(buf,bufCharCnt,fmt,vl);
|
||||||
|
|
||||||
|
if( n > 0 )
|
||||||
|
{
|
||||||
|
// if the print queue exists (it might not during startup or shutdown) ...
|
||||||
|
if( cmTsMp1cIsValid(_printqH) )
|
||||||
|
{
|
||||||
|
cmThRC_t thRC;
|
||||||
|
|
||||||
|
// ... enqueue the text to print
|
||||||
|
if((thRC = cmTsMp1cEnqueueMsg(_printqH,buf,n+1)) != kOkThRC && _printFl==0 )
|
||||||
|
{
|
||||||
|
// Print queue error msg's directly to stdout rather than throught
|
||||||
|
// the error mechanism - this prevents generating a stack overflow
|
||||||
|
// when the print queue runs out of space and attempts to print a
|
||||||
|
// 'queue out of memory' error msg.
|
||||||
|
// The queue itself does will not print errors because it does
|
||||||
|
// not have a valid cmRpt_t pointer. See cmMp1cCreate() above.
|
||||||
|
++_printFl;
|
||||||
|
cmErrMsg(&_ctx->err,kQueueFailAppRC,"Print enqueue failed.");
|
||||||
|
--_printFl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_print(buf); // ... otherwise just send the text directly to the output console
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void app::print( const char* fmt, ... )
|
||||||
|
{
|
||||||
|
va_list vl;
|
||||||
|
va_start(vl,fmt);
|
||||||
|
vprint(fmt,vl);
|
||||||
|
va_end(vl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void app::_s_menu_cb(Fl_Widget* wp, void* data)
|
||||||
|
{
|
||||||
|
const Fl_Menu_Item* mip;
|
||||||
|
app* ap;
|
||||||
|
|
||||||
|
if((ap=_getApp(wp)) != NULL )
|
||||||
|
if((mip = ap->_menu->mvalue()) != NULL )
|
||||||
|
ap->menuCallback(mip,(long int)mip->user_data());
|
||||||
|
}
|
||||||
|
|
||||||
|
void app::_s_menu_btn_cb(Fl_Widget* wp, void* data)
|
||||||
|
{
|
||||||
|
const Fl_Menu_Button* bp;
|
||||||
|
const Fl_Menu_Item* mip;
|
||||||
|
app* ap;
|
||||||
|
|
||||||
|
if((ap=_getApp(wp)) != NULL )
|
||||||
|
if((bp = static_cast<Fl_Menu_Button*>(wp)) != NULL )
|
||||||
|
if((mip = bp->mvalue()) != NULL)
|
||||||
|
ap->menuCallback(mip,(long int)data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void app::_s_btn_cb(Fl_Widget* wp, long data )
|
||||||
|
{
|
||||||
|
app* ap;
|
||||||
|
|
||||||
|
if((ap = _getApp(wp)) != NULL )
|
||||||
|
if( wp != NULL )
|
||||||
|
ap->btnCallback( static_cast<const Fl_Button*>(wp),data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void app::_s_value_cb( Fl_Widget* wp, long data)
|
||||||
|
{
|
||||||
|
app* ap;
|
||||||
|
Fl_Valuator* vp;
|
||||||
|
|
||||||
|
if((ap = _getApp(wp)) != NULL )
|
||||||
|
if((vp = static_cast<Fl_Valuator*>(wp)) != NULL)
|
||||||
|
ap->valueCallback(vp,data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void app::_s_input_cb( Fl_Widget* wp, long data)
|
||||||
|
{
|
||||||
|
app* ap;
|
||||||
|
Fl_Input* inp;
|
||||||
|
|
||||||
|
if((ap = _getApp(wp)) != NULL)
|
||||||
|
if((inp = static_cast<Fl_Input*>(wp)) != NULL )
|
||||||
|
ap->inputCallback(inp,data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void app::_s_callback(Fl_Widget* wp, void* data)
|
||||||
|
{ ((app*)data)->appCallback(wp); }
|
||||||
|
|
||||||
|
void app::_s_idle_cb(void *data)
|
||||||
|
{
|
||||||
|
app* thisPtr = (app*)data;
|
||||||
|
|
||||||
|
if( thisPtr->idleCallback() == false )
|
||||||
|
Fl::remove_idle(_s_idle_cb,data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void app::_s_timer_cb(void* userPtr)
|
||||||
|
{
|
||||||
|
app* thisPtr = (app*)userPtr;
|
||||||
|
|
||||||
|
if( thisPtr->timerCallback() )
|
||||||
|
Fl::repeat_timeout(thisPtr->_timerPeriodSecs,_s_timer_cb,userPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void app::_s_print( void* userPtr, const char* text )
|
||||||
|
{ ((app*)userPtr)->print(text); }
|
||||||
|
|
||||||
|
|
||||||
|
void app::_create_tabs(int titleCnt, const char* titleArray[])
|
||||||
|
{
|
||||||
|
// Create a tab view and added it to the upper splitter area
|
||||||
|
_tabs = new Fl_Tabs(_splt->container1->x(),_splt->container1->y(),_splt->container1->w(),_splt->container1->h());
|
||||||
|
_splt->container1->add(_tabs);
|
||||||
|
|
||||||
|
int tx,ty,th,tw,i;
|
||||||
|
_tabs->client_area(tx,ty,tw,th);
|
||||||
|
|
||||||
|
for(i=0; i<titleCnt; ++i)
|
||||||
|
{
|
||||||
|
_tabs->begin();
|
||||||
|
initializeTab(i,tx,ty,tw,th,titleArray[i]);
|
||||||
|
_tabs->end();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create an empty tab group and make it resizable
|
||||||
|
// to prevent the other tab groups from being resizable.
|
||||||
|
_tabs->begin();
|
||||||
|
_tabs->resizable(new Fl_Group(tx,ty+30,1,1));
|
||||||
|
_tabs->end();
|
||||||
|
}
|
||||||
|
|
||||||
|
app* app::_getApp( Fl_Widget* w )
|
||||||
|
{
|
||||||
|
// walk up the widget tree until the top widget is found
|
||||||
|
Fl_Group* gp = w->parent();
|
||||||
|
while( gp->parent() != NULL )
|
||||||
|
gp=gp->parent();
|
||||||
|
|
||||||
|
// the user data for the top widget is a pointer app - as set in: callback(_s_callback,this);
|
||||||
|
return (app*)gp->user_data();
|
||||||
|
}
|
||||||
|
|
||||||
|
cmRC_t app::_s_print_queue_cb(void* userCbPtr, unsigned msgByteCnt, const void* msgDataPtr )
|
||||||
|
{
|
||||||
|
app* ap = (app*)userCbPtr;
|
||||||
|
ap->_print((const char*)msgDataPtr);
|
||||||
|
return cmOkRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
void app::_checkPrintQueue()
|
||||||
|
{
|
||||||
|
while( cmTsMp1cMsgWaiting(_printqH) )
|
||||||
|
if( cmTsMp1cDequeueMsg(_printqH, NULL, 0) != kOkThRC )
|
||||||
|
error("Print dequeue failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void app::_print( const char* text )
|
||||||
|
{
|
||||||
|
if( _con != NULL )
|
||||||
|
_con->insert(text);
|
||||||
|
}
|
119
src/cmflapp/app.h
Normal file
119
src/cmflapp/app.h
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
#ifndef app_h
|
||||||
|
#define app_h
|
||||||
|
|
||||||
|
class Fl_HSplitter;
|
||||||
|
class Fl_Text_Buffer;
|
||||||
|
class Fl_Text_Display;
|
||||||
|
class Fl_Box;
|
||||||
|
class Fl_Tabs;
|
||||||
|
struct Fl_Menu_Item;
|
||||||
|
class Fl_Menu_Bar;
|
||||||
|
class Fl_Group;
|
||||||
|
class Fl_Button;
|
||||||
|
class Fl_Valuator;
|
||||||
|
class Fl_Input;
|
||||||
|
class drawWnd;
|
||||||
|
|
||||||
|
class app : public Fl_Double_Window
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// widget id's for widgets created by createControls()
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
kFileOpenMId,
|
||||||
|
kFileNewMId,
|
||||||
|
kEditCopyMId,
|
||||||
|
kEditPasteMId,
|
||||||
|
|
||||||
|
kBtn1MId,
|
||||||
|
kBtn2MId,
|
||||||
|
kBtn3MId,
|
||||||
|
|
||||||
|
kMenuBtn1MId,
|
||||||
|
kMenuBtn2MId,
|
||||||
|
|
||||||
|
kValue1MId,
|
||||||
|
kValue2MId,
|
||||||
|
|
||||||
|
kInput1MId
|
||||||
|
};
|
||||||
|
|
||||||
|
app(cmCtx_t* ctx, cmTsMp1cH_t printqH, int w, int h, const char *l, int argc, char *argv[]);
|
||||||
|
virtual ~app();
|
||||||
|
|
||||||
|
// Example tabbed window initialization example function
|
||||||
|
// which also demonstrates some widgets
|
||||||
|
void createControls(Fl_Group* grp);
|
||||||
|
|
||||||
|
// called once from app() to initialize each tabbed window
|
||||||
|
virtual void initializeTab(int tabIndex, int x, int y, int w, int h, const char* label);
|
||||||
|
|
||||||
|
// Create the application menu
|
||||||
|
virtual void createMenu( int menuWidth, int menuHeight );
|
||||||
|
|
||||||
|
// Widget type specific callbacks
|
||||||
|
virtual void menuCallback( const Fl_Menu_Item* ip, long int id ); // menu and menu btn callback
|
||||||
|
virtual void btnCallback( const Fl_Button* bp, int id ); // btn callback
|
||||||
|
virtual void valueCallback(const Fl_Valuator* vp, int id ); // valuator callback
|
||||||
|
virtual void inputCallback(const Fl_Input* ip, int id ); // text input callback
|
||||||
|
|
||||||
|
virtual void appCallback(Fl_Widget* wp); // app event callback
|
||||||
|
virtual bool idleCallback(); // return false to stop callback
|
||||||
|
virtual bool timerCallback(); // return false to stop callback
|
||||||
|
|
||||||
|
void error( const char* fmt, ... ); // report on error
|
||||||
|
|
||||||
|
// print to the console
|
||||||
|
virtual void vprint( const char* fmt, va_list vl );
|
||||||
|
virtual void print( const char* fmt, ... );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
kStatusH = 30,
|
||||||
|
kMenuH = 30,
|
||||||
|
kCtlH = 30
|
||||||
|
};
|
||||||
|
|
||||||
|
// static callbacks
|
||||||
|
static void _s_menu_cb( Fl_Widget* wp, void* data); // menu item callback
|
||||||
|
static void _s_menu_btn_cb(Fl_Widget* wp, void* data); // menu btn callback
|
||||||
|
static void _s_btn_cb( Fl_Widget* wp, long data); // button callback
|
||||||
|
static void _s_value_cb( Fl_Widget* wp, long data); // value input or slider callback
|
||||||
|
static void _s_input_cb( Fl_Widget* wp, long data); // text input callback
|
||||||
|
static void _s_callback( Fl_Widget* wp, void* data); // main app callback
|
||||||
|
|
||||||
|
static void _s_idle_cb( void* data); // idle callback
|
||||||
|
static void _s_timer_cb( void* userPtr); // timer callback
|
||||||
|
static void _s_print( void* userPtr, const char* text ); // print text to the console
|
||||||
|
|
||||||
|
void _create_tabs(int titleCnt, const char* titleArray[]);
|
||||||
|
|
||||||
|
// walk down the widget tree until the app (root) widget is located
|
||||||
|
static app* _getApp( Fl_Widget* w );
|
||||||
|
|
||||||
|
// called internally by cmTsQueueDequeue() to send text to _print()
|
||||||
|
static cmRC_t _s_print_queue_cb(void* userCbPtr, unsigned msgByteCnt, const void* msgDataPtr );
|
||||||
|
|
||||||
|
// called periodically to check the print queue for waiting text.
|
||||||
|
void _checkPrintQueue();
|
||||||
|
|
||||||
|
// send a string of text directly to the output console window
|
||||||
|
void _print( const char* text );
|
||||||
|
|
||||||
|
double _timerPeriodSecs; // repeat period for the timer callback
|
||||||
|
|
||||||
|
cmCtx_t* _ctx; //
|
||||||
|
Fl_HSplitter* _splt; // main splitter window
|
||||||
|
Fl_Text_Buffer* _buf; // text buffer used by _con
|
||||||
|
Fl_Text_Display* _con; // text console output window
|
||||||
|
Fl_Tabs* _tabs; // tabs window
|
||||||
|
Fl_Menu_Bar* _menu; // app. menu
|
||||||
|
drawWnd* _draw; // custom widget
|
||||||
|
cmTsMp1cH_t _printqH; // thread-safe queue for controlling access to the output console from multiple threads
|
||||||
|
int _printFl; // used to prevent recursion due to throwing printing error
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
24
src/cmflapp/appErr.h
Normal file
24
src/cmflapp/appErr.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#ifndef appErr_h
|
||||||
|
#define appErr_h
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
kOkAppRC,
|
||||||
|
kQueueFailAppRC,
|
||||||
|
kFileSysFailAppRC,
|
||||||
|
kMemFailAppRC,
|
||||||
|
kTextSysFailAppRC,
|
||||||
|
kPrefsFailAppRC
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef unsigned cmAppRC_t;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
110
src/cmflapp/main.cpp
Normal file
110
src/cmflapp/main.cpp
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
#include <FL/Fl.H>
|
||||||
|
#include <Fl/fl_draw.H>
|
||||||
|
#include <FL/Fl_Double_Window.H>
|
||||||
|
|
||||||
|
#include "cmPrefix.h"
|
||||||
|
#include "cmGlobal.h"
|
||||||
|
#include "cmFloatTypes.h"
|
||||||
|
#include "cmRpt.h"
|
||||||
|
#include "cmErr.h"
|
||||||
|
#include "cmCtx.h"
|
||||||
|
#include "cmMem.h"
|
||||||
|
#include "cmMallocDebug.h"
|
||||||
|
#include "cmLinkedHeap.h"
|
||||||
|
#include "cmThread.h"
|
||||||
|
#include "cmFileSys.h"
|
||||||
|
#include "cmText.h"
|
||||||
|
|
||||||
|
#include "appErr.h"
|
||||||
|
#include "app.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void print( void*, const cmChar_t* text)
|
||||||
|
{ puts(text); }
|
||||||
|
|
||||||
|
cmRC_t print_queue_cb(void* userCbPtr, unsigned msgByteCnt, const void* msgDataPtr )
|
||||||
|
{
|
||||||
|
print(NULL,(const char*)msgDataPtr);
|
||||||
|
return cmOkRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main( int argc, char* argv[] )
|
||||||
|
{
|
||||||
|
cmCtx_t ctx;
|
||||||
|
cmTsMp1cH_t printqH = cmTsMp1cNullHandle;
|
||||||
|
int appWndW = 1000;
|
||||||
|
int appWndH = 750;
|
||||||
|
const char* appPrefDir = "gv";
|
||||||
|
const char* appTitle = "GV Console";
|
||||||
|
bool memDebugFl = cmDEBUG_FL;
|
||||||
|
unsigned memPadByteCnt = memDebugFl ? 8 : 0;
|
||||||
|
unsigned memAlignByteCnt = 16;
|
||||||
|
unsigned memFlags = memDebugFl ? (kTrackMmFl | kDeferFreeMmFl | kFillUninitMmFl) : 0;
|
||||||
|
|
||||||
|
cmCtxSetup(&ctx,appTitle,print,print,NULL,memPadByteCnt,memAlignByteCnt,memFlags);
|
||||||
|
|
||||||
|
// initialize the memory mgr
|
||||||
|
if(cmMdInitialize( memPadByteCnt, memAlignByteCnt, memFlags, &ctx.rpt ) != kOkMmRC )
|
||||||
|
{
|
||||||
|
cmErrMsg(&ctx.err,kMemFailAppRC,"Heap initialization failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize the file system
|
||||||
|
if( cmFsInitialize( &ctx, appPrefDir ) != kOkFsRC )
|
||||||
|
cmErrMsg(&ctx.err,kFileSysFailAppRC,"File system initialization failed.");
|
||||||
|
|
||||||
|
// initialize the text system
|
||||||
|
if( cmTsInitialize(&ctx) != kOkTxRC )
|
||||||
|
cmErrMsg(&ctx.err,kTextSysFailAppRC,"Text system initialization failed.");
|
||||||
|
|
||||||
|
// create the print queue
|
||||||
|
if( cmTsMp1cCreate( &printqH, 8192, print_queue_cb, NULL, NULL ) != kOkThRC )
|
||||||
|
cmErrMsg(&ctx.err,kQueueFailAppRC,"Print queue creation failed.");
|
||||||
|
|
||||||
|
|
||||||
|
if( cmErrLastRC(&ctx.err) == kOkAppRC )
|
||||||
|
{
|
||||||
|
app proj(&ctx, printqH, appWndW, appWndH, appTitle, argc, argv);
|
||||||
|
Fl::run();
|
||||||
|
|
||||||
|
// reset the pgm context and print queue console output to stdout
|
||||||
|
cmRptSetup(&ctx.rpt,print,print,NULL);
|
||||||
|
cmTsMp1cSetCbFunc(printqH, print_queue_cb, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
// empty any pending text to stdout
|
||||||
|
while( cmTsMp1cMsgWaiting(printqH) )
|
||||||
|
if( cmTsMp1cDequeueMsg(printqH, NULL, 0) != kOkThRC )
|
||||||
|
cmErrMsg(&ctx.err,kQueueFailAppRC,"Print dequeue failed.");
|
||||||
|
|
||||||
|
// destroy the print queue
|
||||||
|
if( cmTsMp1cDestroy(&printqH) != kOkThRC )
|
||||||
|
cmErrMsg(&ctx.err,kQueueFailAppRC,"Print queue destroy failed.");
|
||||||
|
|
||||||
|
// finalize the text system
|
||||||
|
if( cmTsFinalize() != kOkTxRC )
|
||||||
|
cmErrMsg(&ctx.err,kTextSysFailAppRC,"Text system finalization failed.");
|
||||||
|
|
||||||
|
// finalize the file system
|
||||||
|
if( cmFsFinalize() != kOkFsRC )
|
||||||
|
cmErrMsg(&ctx.err,kFileSysFailAppRC,"File system finalize failed.");
|
||||||
|
|
||||||
|
// report memory mgr errors
|
||||||
|
if( cmMdIsValid() )
|
||||||
|
cmMdReport( kIgnoreNormalMmFl );
|
||||||
|
|
||||||
|
// finalize the memory manager
|
||||||
|
if( cmMdFinalize() != kOkMmRC )
|
||||||
|
cmErrMsg(&ctx.err,kMemFailAppRC,"Heap finalization failed.");
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -1,39 +0,0 @@
|
|||||||
#include "cmPrefix.h"
|
|
||||||
#include "cmGlobal.h"
|
|
||||||
#include "cmRpt.h"
|
|
||||||
#include "cmErr.h"
|
|
||||||
#include "cmCtx.h"
|
|
||||||
#include "cmMem.h"
|
|
||||||
#include "cmMallocDebug.h"
|
|
||||||
#include "cmLinkedHeap.h"
|
|
||||||
#include "cmFileSys.h"
|
|
||||||
#include "cmText.h"
|
|
||||||
|
|
||||||
void print( void* arg, const char* text )
|
|
||||||
{
|
|
||||||
printf("%s\n",text);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main( int argc, char* argv[] )
|
|
||||||
{
|
|
||||||
// initialize the heap check library
|
|
||||||
bool memDebugFl = cmDEBUG_FL;
|
|
||||||
unsigned memGuardByteCnt = memDebugFl ? 8 : 0;
|
|
||||||
unsigned memAlignByteCnt = 16;
|
|
||||||
unsigned memFlags = memDebugFl ? kTrackMmFl | kDeferFreeMmFl | kFillUninitMmFl : 0;
|
|
||||||
|
|
||||||
cmCtx_t ctx;
|
|
||||||
cmCtxSetup(&ctx,"cm test",print,print,NULL,memGuardByteCnt,memAlignByteCnt,memFlags);
|
|
||||||
|
|
||||||
cmMdInitialize( memGuardByteCnt, memAlignByteCnt, memFlags, &ctx.rpt );
|
|
||||||
|
|
||||||
cmFsInitialize( &ctx, "cm_test" );
|
|
||||||
|
|
||||||
cmTsInitialize(&ctx );
|
|
||||||
|
|
||||||
cmTsFinalize();
|
|
||||||
cmFsFinalize();
|
|
||||||
cmMdReport( kIgnoreNormalMmFl );
|
|
||||||
cmMdFinalize();
|
|
||||||
return 0;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user