Browse Source

Initial commit

master
kpl 11 years ago
parent
commit
7e8b9b5570
9 changed files with 1154 additions and 45 deletions
  1. 5
    4
      Makefile.am
  2. 2
    2
      configure.ac
  3. 265
    0
      src/cmflapp/Fl_Splitter.cpp
  4. 74
    0
      src/cmflapp/Fl_Splitter.h
  5. 555
    0
      src/cmflapp/app.cpp
  6. 119
    0
      src/cmflapp/app.h
  7. 24
    0
      src/cmflapp/appErr.h
  8. 110
    0
      src/cmflapp/main.cpp
  9. 0
    39
      src/proj/main.c

+ 5
- 4
Makefile.am View File

@@ -15,7 +15,7 @@ AM_CPPFLAGS = -D _GNU_SOURCE  -I.. -I$(srcdir)/src/libcm  -I$(srcdir)/src/libcm/
15 15
 AM_CFLAGS   = -Wno-multichar 
16 16
 AM_CXXFLAGS = 
17 17
 AM_LDFLAGS  =  
18
-MYLIBS      = -lpthread  -lfftw3f -lfftw3
18
+MYLIBS      = -lpthread  -lfftw3f -lfftw3 -lfltk
19 19
 CMLIBS      = src/libcm/libcm.la  # autoconfig manual recommends storing direct referenes to non-3rd party libraries rather than using -L and -l
20 20
 
21 21
 
@@ -56,6 +56,7 @@ include_HEADERS += $(cmHDR)
56 56
 lib_LTLIBRARIES += src/libcm/libcm.la
57 57
 
58 58
 
59
-src_proj_proj_SOURCES  = src/proj/main.c
60
-src_proj_proj_LDADD    = $(CMLIBS) $(MYLIBS)
61
-bin_PROGRAMS          += src/proj/proj
59
+src_cmflapp_cmflapp_SOURCES  = src/cmflapp/main.cpp src/cmflapp/app.h src/cmflapp/app.cpp 
60
+src_cmflapp_cmflapp_SOURCES += src/cmflapp/Fl_Splitter.h src/cmflapp/Fl_Splitter.cpp
61
+src_cmflapp_cmflapp_LDADD    = $(CMLIBS) $(MYLIBS)
62
+bin_PROGRAMS                += src/cmflapp/cmflapp

+ 2
- 2
configure.ac View File

@@ -3,10 +3,10 @@
3 3
 # this configure.ac or any of the Makefile.am files.
4 4
 #
5 5
 
6
-AC_INIT([proj],[1.0],[proj@larke.org])
6
+AC_INIT([cmflapp],[1.0],[cmflapp@larke.org])
7 7
 AC_CONFIG_AUX_DIR([build-aux])                    # put aux files in build-aux
8 8
 AM_INIT_AUTOMAKE([1.9 -Wall foreign subdir-objects]) # subdir-objects needed for non-recursive make
9
-AC_CONFIG_SRCDIR([src/proj/main.c])
9
+AC_CONFIG_SRCDIR([src/cmflapp/main.cpp])
10 10
 AC_CONFIG_HEADERS([config.h])
11 11
 AC_CONFIG_MACRO_DIR([m4])
12 12
 

+ 265
- 0
src/cmflapp/Fl_Splitter.cpp View File

@@ -0,0 +1,265 @@
1
+// Code based on: http://www.mail-archive.com/fltk@easysw.com/msg04573.html
2
+// Lucas Sanner/Ian MacArthur
3
+
4
+#include "Fl_Splitter.h"
5
+
6
+void Fl_HSplitter::draw()
7
+{
8
+  Fl_Group::draw();
9
+  fl_color(FL_BLACK);
10
+  fl_line_style( FL_DOT, 1);
11
+
12
+  if(bSplit && Fl::event_button1() != 0)
13
+  {
14
+    fl_push_clip(x(), y(), w(), h());
15
+
16
+    yPos = Fl::event_y();
17
+
18
+    if(Fl::event_y() > h() - (border * 2))
19
+      yPos = h() - (border * 2);
20
+
21
+    if(Fl::event_y() < y() + (border * 2))
22
+      yPos = y() + (border * 2);
23
+
24
+    fl_line( x() + border, yPos - 1, x() + w() - (border*2), yPos - 1 );
25
+    fl_line( x() + border, yPos    , x() + w() - (border*2), yPos     );
26
+    fl_line( x() + border, yPos + 1, x() + w() - (border*2), yPos + 1 );
27
+
28
+    /*
29
+    fl_line(
30
+      x() + border,
31
+      yPos,
32
+      x() + w() - (border*2),
33
+      yPos );
34
+
35
+    fl_line(
36
+      x() + border,
37
+      yPos + 1,
38
+      x() + w() - (border*2),
39
+      yPos + 1 );
40
+    */  
41
+
42
+    fl_pop_clip();
43
+  }
44
+  else
45
+  {
46
+    fl_push_clip(x(), y(), w(), h());
47
+    fl_pop_clip();
48
+  }
49
+}
50
+
51
+int Fl_HSplitter::handle(int e)
52
+{
53
+  int ret = Fl_Group::handle(e);
54
+
55
+  switch(e)
56
+  {
57
+    case FL_MOVE:
58
+
59
+      if(Fl::event_y() > hCtnl - border && Fl::event_y() < hCtnl + border)
60
+      {
61
+        fl_cursor(FL_CURSOR_NS);
62
+        bSplit = true;
63
+      }
64
+      else
65
+      {
66
+        fl_cursor(FL_CURSOR_DEFAULT);
67
+        bSplit = false;
68
+      }
69
+
70
+      return 1;
71
+
72
+    case FL_PUSH:
73
+
74
+      if(Fl::event_button() == FL_LEFT_MOUSE && bSplit)
75
+      {
76
+        redraw();
77
+      }
78
+
79
+      return 1;
80
+
81
+    case FL_RELEASE:
82
+
83
+      if(Fl::event_button() == FL_LEFT_MOUSE && bSplit)
84
+      {
85
+        container1->resize(x(), y(), w(), yPos - y());
86
+        hCtnl = yPos;
87
+        container2->resize(x(),hCtnl, w(), h() - (yPos - y()));
88
+        
89
+        if( stretchTopFl )
90
+          init_sizes();
91
+
92
+        bSplit = false;
93
+        redraw();
94
+      }
95
+
96
+      return 1;
97
+
98
+    case FL_DRAG:
99
+
100
+      if(bSplit && Fl::event_state(FL_BUTTON1) != 0)
101
+        redraw();
102
+
103
+      return 1;
104
+  }
105
+
106
+  return(ret);
107
+}
108
+
109
+
110
+Fl_HSplitter::Fl_HSplitter(int x, int y, int w, int h, int h1, const char *l, bool stretchBotFl)
111
+  : Fl_Group(x, y, w, h, l)
112
+{
113
+  int h2 = h - h1;
114
+
115
+  begin();
116
+  container1 = new Splitter_Container(x, y, w, h1);
117
+  //container1->color((Fl_Color) FL_RED);
118
+  end();
119
+
120
+  begin();
121
+  container2 = new Splitter_Container(x, y + h1, w, h2);
122
+  //container2->color((Fl_Color) FL_BLUE);
123
+  end();
124
+
125
+  hCtnl =  y + h1;
126
+  bSplit = false;
127
+  stretchTopFl = !stretchBotFl;
128
+
129
+  border = Fl::box_dy(FL_DOWN_BOX);
130
+
131
+  if( stretchTopFl )
132
+    resizable(container1);
133
+}
134
+
135
+void Fl_HSplitter::resize_splitter(int x, int y, int w, int h)
136
+{
137
+  resize(x, y, w, h);
138
+
139
+  if( stretchTopFl )
140
+  {
141
+    hCtnl = container1->h() + y;
142
+    yPos = hCtnl;
143
+  }
144
+  else
145
+  {
146
+    container1->resize(x, y,     w,     hCtnl - y);
147
+    container2->resize(x, hCtnl, w, h - (hCtnl - y));
148
+  }
149
+
150
+}
151
+
152
+
153
+
154
+void Fl_VSplitter::draw()
155
+{
156
+  Fl_Group::draw();
157
+  fl_color(FL_BLACK);
158
+  fl_line_style( FL_DOT, 1);
159
+
160
+  if(bSplit && Fl::event_button1() != 0)
161
+  {
162
+    fl_push_clip(x(), y(), w(), h());
163
+
164
+    xPos = Fl::event_x();
165
+
166
+    if(Fl::event_x() > w() - (border * 2))
167
+      xPos = w() - (border * 2);
168
+
169
+    if(Fl::event_x() < x() + (border * 2))
170
+      xPos = x() + (border * 2);
171
+
172
+    fl_line(xPos - 1, y() + border, xPos - 1, y() + h() - (border * 2));
173
+    fl_line(xPos, y() + border, xPos, y() + h() - (border * 2));
174
+    fl_line(xPos + 1, y() + border, xPos + 1, y() + h() - (border * 2));
175
+
176
+    fl_pop_clip();
177
+  }
178
+  else
179
+  {
180
+    fl_push_clip(x(), y(), w(), h());
181
+    fl_pop_clip();
182
+  }
183
+}
184
+
185
+int Fl_VSplitter::handle(int e)
186
+{
187
+  int ret = Fl_Group::handle(e);
188
+
189
+  switch(e)
190
+  {
191
+    case FL_MOVE:
192
+
193
+      if(Fl::event_x() > wCtn1 - border && Fl::event_x() < wCtn1 + border)
194
+      {
195
+        fl_cursor(FL_CURSOR_WE);
196
+        bSplit = true;
197
+      }
198
+      else
199
+      {
200
+        fl_cursor(FL_CURSOR_DEFAULT);
201
+        bSplit = false;
202
+      }
203
+
204
+      return 1;
205
+
206
+    case FL_PUSH:
207
+
208
+      if(Fl::event_button() == FL_LEFT_MOUSE && bSplit)
209
+      {
210
+        redraw();
211
+      }
212
+
213
+      return 1;
214
+
215
+    case FL_RELEASE:
216
+
217
+      if(Fl::event_button() == FL_LEFT_MOUSE && bSplit)
218
+      {
219
+        container1->resize(x(), y(), xPos, h());
220
+        wCtn1 = xPos;
221
+        container2->resize(wCtn1, y(), w() - wCtn1, h());
222
+        bSplit = false;
223
+        redraw();
224
+      }
225
+
226
+      return 1;
227
+
228
+    case FL_DRAG:
229
+
230
+      if(bSplit && Fl::event_state(FL_BUTTON1) != 0)
231
+        redraw();
232
+
233
+      return 1;
234
+  }
235
+
236
+  return(ret);
237
+}
238
+
239
+Fl_VSplitter::Fl_VSplitter(int x, int y, int w, int h, const char *l)
240
+  : Fl_Group(x, y, w, h, l)
241
+{
242
+  begin();
243
+  container1 = new Splitter_Container(x, y, w / 2, h);
244
+  //container1->color((Fl_Color) FL_RED);
245
+  end();
246
+
247
+  begin();
248
+  container2 = new Splitter_Container(x + (w / 2), y, w / 2, h);
249
+  //container2->color((Fl_Color) FL_BLUE);
250
+  end();
251
+
252
+  wCtn1 = w / 2;
253
+  bSplit = false;
254
+
255
+  border = Fl::box_dx(FL_DOWN_BOX);
256
+
257
+}
258
+
259
+void Fl_VSplitter::resize_splitter(int x, int y, int w, int h)
260
+{
261
+  resize(x, y, w, h);
262
+  container1->resize(x, y, wCtn1, h);
263
+  container2->resize(wCtn1, y, w - wCtn1, h);
264
+}
265
+

+ 74
- 0
src/cmflapp/Fl_Splitter.h View File

@@ -0,0 +1,74 @@
1
+// Code based on: http://www.mail-archive.com/fltk@easysw.com/msg04573.html
2
+// Lucas Sanner/Ian MacArthur
3
+
4
+#ifndef Fl_Splitter_h
5
+#define Fl_Splitter_h
6
+
7
+#include <FL/Fl.H>
8
+#include <FL/Fl_Group.H>
9
+#include <FL/Fl_Box.H>
10
+#include <FL/fl_draw.H>
11
+
12
+
13
+class Splitter_Container : public Fl_Group
14
+{
15
+  void draw()
16
+  {
17
+    fl_push_clip(x(), y(), w(), h());
18
+    Fl_Group::draw();
19
+    fl_pop_clip();
20
+  }
21
+
22
+  public:
23
+
24
+    Splitter_Container(int x, int y, int w, int h, char *l = NULL)
25
+    : Fl_Group(x, y, w, h, l)
26
+    {
27
+      //box(FL_DOWN_BOX);
28
+    }
29
+};
30
+
31
+class Fl_HSplitter : public Fl_Group
32
+{
33
+  int hCtnl, border, yPos;
34
+  bool bSplit;
35
+  bool stretchTopFl;  // set to make top container stretch when splitter is resized
36
+  int  hh2;
37
+
38
+  void draw();
39
+
40
+  int handle(int e);
41
+
42
+  public:
43
+
44
+  Splitter_Container *container1, *container2;
45
+
46
+  Fl_HSplitter(int x, int y, int w, int h, int h1, const char *l=NULL, bool stretchBotFl=false);
47
+
48
+  void resize_splitter(int x, int y, int w, int h);
49
+
50
+};
51
+
52
+
53
+class Fl_VSplitter : public Fl_Group
54
+{
55
+
56
+  int wCtn1, border, xPos;
57
+  bool bSplit;
58
+
59
+  void draw();
60
+  int handle(int e);
61
+
62
+  public:
63
+
64
+  Splitter_Container *container1, *container2;
65
+
66
+  Fl_VSplitter(int x, int y, int w, int h, const char *l = NULL);
67
+
68
+  void resize_splitter(int x, int y, int w, int h);
69
+
70
+
71
+
72
+};
73
+
74
+#endif

+ 555
- 0
src/cmflapp/app.cpp View File

@@ -0,0 +1,555 @@
1
+#include <FL/Fl.H>
2
+#include <FL/Fl_Widget.H>
3
+#include <FL/Fl_Double_Window.H>
4
+#include <FL/Fl_Text_Buffer.H>
5
+#include <FL/Fl_Text_Display.H>
6
+#include <FL/Fl_Tabs.H>
7
+#include <FL/Fl_Menu_Item.H>
8
+#include <FL/Fl_Menu_Bar.H>
9
+#include <FL/Fl_Button.H>
10
+#include <FL/Fl_Check_Button.H>
11
+#include <FL/Fl_Menu_Button.H>
12
+#include <FL/Fl_Value_Input.H>
13
+#include <FL/Fl_Value_Slider.H>
14
+#include <FL/Fl_Input.H>
15
+#include <FL/Fl_Box.H>
16
+#include <FL/Fl_File_Chooser.H>
17
+#include <FL/fl_draw.H>
18
+
19
+#include "Fl_Splitter.h"
20
+
21
+#include "cmPrefix.h"
22
+#include "cmGlobal.h"
23
+#include "cmRpt.h"
24
+#include "cmErr.h"
25
+#include "cmCtx.h"
26
+#include "cmMem.h"
27
+#include "cmMallocDebug.h"
28
+#include "cmFileSys.h"
29
+#include "cmThread.h"
30
+
31
+#include "appErr.h"
32
+#include "app.h"
33
+
34
+class drawWnd : public Fl_Widget
35
+{
36
+public:
37
+  drawWnd(app* ap, int x, int y, int w, int h, const char* label = NULL );
38
+  virtual ~drawWnd();
39
+
40
+  virtual int handle(int event);
41
+  virtual void resize(int x, int y, int w, int h );
42
+
43
+protected:
44
+  virtual void draw();
45
+
46
+private:
47
+  app* _app;
48
+};
49
+
50
+drawWnd::drawWnd(app* ap, int x, int y, int w, int h, const char* label )
51
+  : Fl_Widget(x,y,w,h,label),
52
+    _app(ap)
53
+{}
54
+
55
+drawWnd::~drawWnd()
56
+{}
57
+
58
+int drawWnd::handle(int event)
59
+{
60
+  switch(event)
61
+  {
62
+    case FL_PUSH:
63
+      {
64
+        const char* label;
65
+        switch( Fl::event_button() )
66
+        {
67
+          case FL_LEFT_MOUSE:   label = "left";  break;
68
+          case FL_RIGHT_MOUSE:  label = "right";  break;
69
+          case FL_MIDDLE_MOUSE: label = "middle"; break;
70
+          default:
71
+            label = "none";
72
+        }
73
+
74
+        _app->print("%i %i %s\n",Fl::event_x(),Fl::event_y(),label);
75
+      }
76
+      break;
77
+
78
+    default:
79
+      return Fl_Widget::handle(event);
80
+  }
81
+
82
+  return 1;
83
+}
84
+
85
+void drawWnd::resize(int x, int y, int w, int h )
86
+{ 
87
+  // must call base to make size change
88
+  Fl_Widget::resize(x,y,w,h); 
89
+}
90
+
91
+void drawWnd::draw()
92
+{
93
+  int offs = 10;
94
+  //fl_draw_box(FL_DOWN_BOX,x()+10,y()+10,w()-20,h()-20,FL_RED);
95
+  //fl_frame("XXXX",x()+offs,y()+offs,w()-2*offs,h()-2*offs);
96
+  fl_line_style(FL_SOLID,1,NULL);
97
+  fl_color(FL_RED);
98
+  fl_line(x()+offs,y()+offs,x()+w()-offs,y()+h()-offs);
99
+
100
+
101
+  int x = w()/2;
102
+  int y = h()/2;
103
+
104
+  fl_color(FL_BLACK);
105
+  fl_draw(90,"string",x,y);
106
+
107
+  // XXXXXXX
108
+  // X00000X
109
+  // X00000X
110
+  // X00X00X
111
+  // X00000X
112
+  // X00000X
113
+  // XXXXXXX
114
+
115
+  fl_rect(x-3,y-3,7,7); 
116
+  fl_point(x,y);
117
+}
118
+
119
+//----------------------------------------------------------------------------------------------------
120
+//----------------------------------------------------------------------------------------------------
121
+//----------------------------------------------------------------------------------------------------
122
+
123
+app::app(cmCtx_t* ctx, cmTsMp1cH_t printqH, int w, int h, const char* label, int argc, char* argv[])
124
+  : Fl_Double_Window(w,h,label), _timerPeriodSecs(0),
125
+    _ctx(ctx), _splt(NULL),_buf(NULL),_con(NULL),_tabs(NULL),_menu(NULL),
126
+    _printqH(printqH),_printFl(0)
127
+{
128
+
129
+  // install a callback to cleanup when the app window closes
130
+  // (the btn and menu callbacks also rely on a pointer to 'this' being found in app.user_data()
131
+  //  see _getApp())
132
+  callback(_s_callback,this);
133
+
134
+  // the main window is divided between the menu bar on top
135
+  // and a horizontal splitter on the bottom
136
+  begin();
137
+  createMenu(w,kMenuH);
138
+  _splt = new Fl_HSplitter(0, kMenuH, w, h-kStatusH, h-kStatusH-100);
139
+  end();
140
+
141
+  // Create a text display object for console output and
142
+  // add it to the lower splitter area
143
+  _buf = new Fl_Text_Buffer();
144
+  _con = new Fl_Text_Display(_splt->container2->x(),_splt->container2->y(),_splt->container2->w(),_splt->container2->h());
145
+  _con->buffer(_buf);
146
+  _splt->container2->add(_con);
147
+
148
+  // create tabbed windows
149
+  const char* titles[] = { "Title 1", "Title 2" };
150
+  _create_tabs(2,titles);
151
+
152
+  // make the splitter the resizable group element (thereby making the menu non-resizable).
153
+  // see:http://fltk.org/articles.php?L415+I0+T+M1000+P1
154
+  resizable(_splt); 
155
+  show(argc, argv);
156
+
157
+  // The application is now visible.
158
+  // direct all output to the console window
159
+  cmRptSetup(&_ctx->rpt,_s_print,_s_print, this);
160
+  cmTsMp1cSetCbFunc(_printqH, _s_print_queue_cb, this );
161
+
162
+
163
+  // install a timer
164
+  _timerPeriodSecs = 0.1;
165
+  Fl::add_timeout(_timerPeriodSecs,app::_s_timer_cb,this);
166
+
167
+  // install an idle callback 
168
+  //Fl::add_idle(_s_idle_cb,this);
169
+
170
+  print("Started!\n");
171
+}
172
+
173
+app::~app()
174
+{}
175
+
176
+void app::createControls(Fl_Group* grp)
177
+{
178
+  const int vBord     = 3;
179
+  const int ctl_width = 100;
180
+  int       xx        = grp->x() + 5;
181
+  int       yy        = grp->y() + vBord;
182
+
183
+  Fl_Check_Button* cbt = new Fl_Check_Button(xx,yy,ctl_width,kCtlH,"Check");
184
+  cbt->callback( _s_btn_cb, kBtn1MId );
185
+  yy += cbt->h() + vBord;
186
+
187
+  Fl_Button* btn = new Fl_Button(xx,yy,ctl_width,kCtlH,"Button");
188
+  btn->callback( _s_btn_cb, kBtn2MId );
189
+  yy += btn->h() + vBord;
190
+
191
+  // menu buttons callback through menuCallback() not btnCallback()
192
+  Fl_Menu_Button* mbt  = new Fl_Menu_Button(xx,yy,ctl_width,kCtlH,"Menu");
193
+  
194
+  mbt->add("Item 1",0,_s_menu_btn_cb, (void*)kMenuBtn1MId, 0);
195
+  mbt->add("Item 2",0,_s_menu_btn_cb, (void*)kMenuBtn2MId, 0);
196
+  yy += mbt->h() + vBord;
197
+
198
+  Fl_Value_Input* vip = new Fl_Value_Input(xx,yy,ctl_width/2,kCtlH,"Value In");
199
+  vip->callback(_s_value_cb, kValue1MId );
200
+  vip->align(FL_ALIGN_RIGHT);   // place label to the right of the input ctl
201
+  // Only make the callback when the enter key is struck or the ctl loses focus and the value has changed.
202
+  // Removing this line causes the callback whenever the input changes.
203
+  vip->when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE ); 
204
+  vip->bounds(-10.0,10.0);
205
+  vip->step(0.1);
206
+  yy += vip->h() + vBord;
207
+  
208
+  Fl_Value_Slider* sdp =    new Fl_Value_Slider(xx,yy,ctl_width,kCtlH,"Slider");
209
+  sdp->callback(_s_value_cb, kValue2MId );
210
+  sdp->align(FL_ALIGN_RIGHT);
211
+  sdp->type(FL_HOR_NICE_SLIDER);
212
+  sdp->bounds(-10.0,10.0);
213
+  sdp->step(0.1);
214
+  yy += sdp->h() + vBord;
215
+
216
+  Fl_Input* inp = new Fl_Input(xx,yy,ctl_width/2,kCtlH,"Text");
217
+  inp->callback(_s_input_cb,kInput1MId);
218
+  inp->align(FL_ALIGN_RIGHT);
219
+  yy += inp->h() + vBord;
220
+
221
+
222
+}
223
+
224
+
225
+void app::initializeTab(int tabIndex, int x, int y, int w, int h, const char* label)
226
+{
227
+  switch(tabIndex)
228
+  {
229
+    case 0:
230
+      {
231
+        Fl_Group* grp = new Fl_Group(x,y,w,h,label);  
232
+        grp->begin();
233
+        createControls(grp);
234
+        grp->end();
235
+      }
236
+      break;
237
+
238
+    case 1:
239
+      {
240
+        Fl_Group* grp = new Fl_Group(x,y,w,h,label);  
241
+        grp->begin();
242
+        _draw = new drawWnd(this,x,y,w,h,NULL);
243
+        grp->end();
244
+      }
245
+      break;
246
+  }
247
+
248
+}
249
+
250
+void app::createMenu(int w, int h)
251
+{
252
+  Fl_Menu_Item items[] =
253
+  {
254
+    { "&File", 0, 0, 0, FL_SUBMENU },
255
+    { "&New File",  FL_COMMAND + 'n', (Fl_Callback*)_s_menu_cb, (void*)kFileNewMId },
256
+    { "&Open File", FL_COMMAND + 'o', (Fl_Callback*)_s_menu_cb, (void*)kFileOpenMId },
257
+    { 0 },
258
+    { "&Edit", 0, 0, 0, FL_SUBMENU },
259
+    { "&Copy",  FL_COMMAND + 'c', (Fl_Callback*)_s_menu_cb, (void*)kEditCopyMId },
260
+    { "&Paste", FL_COMMAND + 'v', (Fl_Callback*)_s_menu_cb, (void*)kEditPasteMId },
261
+    { 0 },
262
+    { 0 }
263
+  };
264
+  
265
+  _menu = new Fl_Menu_Bar(0,0,w,h);
266
+  _menu->copy(items);
267
+}
268
+
269
+void app::menuCallback(const Fl_Menu_Item* mip, long int id)
270
+{
271
+  switch(id)
272
+  {
273
+    case kFileOpenMId:
274
+      {
275
+        // file chooser demo
276
+
277
+        const char* pathStr   = cmFsUserDir(); // make the default dir the user's home dir
278
+        const char patStr[]   = "Text Files (*.txt)\tAudio Files (*.{wav,aif,aiff})"; // All Files (*.*) is append to this automatically
279
+        const char titleStr[] = "Select files";
280
+
281
+        Fl_File_Chooser fc = Fl_File_Chooser(pathStr,patStr,Fl_File_Chooser::MULTI,titleStr);
282
+
283
+        fc.preview(0); // default the previous option to 'off'.
284
+        fc.show();     // show the chooser
285
+
286
+        // make the chooser modal
287
+        while( fc.shown() )
288
+          Fl::wait();
289
+
290
+        // print the selected files
291
+        int i;
292
+        for(i=1; i<=fc.count(); ++i)
293
+          print("%i %s\n",i,cmStringNullGuard(fc.value(i)));
294
+
295
+      }
296
+      break;
297
+  }
298
+
299
+  print("%i %s\n",id,mip->label());
300
+}
301
+
302
+void app::btnCallback(const Fl_Button* bp, int id )
303
+{
304
+  print("%i %s %i\n",id,bp->label(),bp->value());
305
+}
306
+
307
+void app::valueCallback(const Fl_Valuator*  vp, int id )
308
+{
309
+  print("%i %s %f\n",id,vp->label(),vp->value());
310
+}
311
+
312
+void app::inputCallback(const Fl_Input*  ip, int id )
313
+{
314
+  print("%i %s %s\n",id,ip->label(),ip->value());
315
+}
316
+
317
+void app::appCallback(Fl_Widget* wp)
318
+{
319
+  switch( Fl::event() )
320
+  {
321
+    case FL_CLOSE:
322
+      {
323
+
324
+        /*
325
+        int cc = _closeCnt;
326
+
327
+        // attempt to shut down the pgm
328
+        _closeCnt += finalizePgm() == false;
329
+
330
+        // the first time the pgm fails to shut down 
331
+        // do not allow the pgm to close the main window
332
+        // this will give a chance for the error messages
333
+        // to be diplayed in the console - all successive
334
+        // times the return value from finalizePgm() is
335
+      
336
+        // ignored and the program is terminated.
337
+        if( _closeCnt == 1 && cc==0)
338
+        {
339
+          // send a strong hint that a problem occurred on shutdown 
340
+          // and prevent the app from receiving events that might cause it to 
341
+          // crash
342
+          deactivate(); 
343
+          return;
344
+        }
345
+        */
346
+
347
+        // When all windows are windows are closed then the app.
348
+        // will close - so hiding the application window
349
+        // causes the program to close.  
350
+        //
351
+        // Note that simply returning from this callback will
352
+        // prevent the application from closing. Because the existence
353
+        // of the callback alone is enough to disable default 
354
+        // event handling.
355
+        hide();  
356
+      }
357
+      break;
358
+  }
359
+
360
+}
361
+bool app::idleCallback()
362
+{ return true; }
363
+
364
+
365
+bool app::timerCallback()
366
+{ 
367
+  _checkPrintQueue();
368
+  return true;
369
+}
370
+
371
+void app::error( const char* fmt, ... )
372
+{
373
+  va_list vl;
374
+  va_start(vl,fmt);
375
+
376
+  int bufCharCnt = 511;
377
+  char buf[bufCharCnt+1];
378
+
379
+  int n = vsnprintf(buf,bufCharCnt,fmt,vl);
380
+
381
+  if( n > 0 )
382
+    print("%s Error: %s\n",label(),buf);
383
+  
384
+  va_end(vl);
385
+}
386
+
387
+void app::vprint(const char* fmt, va_list vl )
388
+{
389
+  int bufCharCnt = 511;
390
+  char buf[bufCharCnt+1];
391
+
392
+  int n = vsnprintf(buf,bufCharCnt,fmt,vl);
393
+
394
+  if( n > 0 )
395
+  {
396
+    // if the print queue exists (it might not during startup or shutdown) ...
397
+    if( cmTsMp1cIsValid(_printqH) )
398
+    {
399
+      cmThRC_t thRC;
400
+
401
+      // ... enqueue the text to print 
402
+      if((thRC = cmTsMp1cEnqueueMsg(_printqH,buf,n+1)) != kOkThRC && _printFl==0 )
403
+      {
404
+        // Print queue error msg's directly to stdout rather than throught
405
+        // the error mechanism - this prevents generating a stack overflow
406
+        // when the print queue runs out of space and attempts to print a 
407
+        // 'queue out of memory' error msg.
408
+        // The queue itself does will not print errors because it does
409
+        // not have a valid cmRpt_t pointer.  See cmMp1cCreate() above.
410
+        ++_printFl;
411
+        cmErrMsg(&_ctx->err,kQueueFailAppRC,"Print enqueue failed.");
412
+        --_printFl;
413
+      }
414
+    }
415
+    else
416
+      _print(buf); // ... otherwise just send the text directly to the output console
417
+  }
418
+
419
+}
420
+
421
+void app::print( const char* fmt, ... )
422
+{
423
+  va_list vl;
424
+  va_start(vl,fmt);
425
+  vprint(fmt,vl);
426
+  va_end(vl);
427
+}
428
+
429
+void app::_s_menu_cb(Fl_Widget* wp, void* data)
430
+{ 
431
+  const Fl_Menu_Item* mip;
432
+  app*                ap;
433
+
434
+  if((ap=_getApp(wp)) != NULL )
435
+    if((mip = ap->_menu->mvalue()) != NULL )
436
+      ap->menuCallback(mip,(long int)mip->user_data());
437
+}
438
+
439
+void app::_s_menu_btn_cb(Fl_Widget* wp, void* data)
440
+{ 
441
+  const Fl_Menu_Button* bp;
442
+  const Fl_Menu_Item*   mip;
443
+  app*                  ap;
444
+
445
+  if((ap=_getApp(wp)) != NULL )
446
+    if((bp = static_cast<Fl_Menu_Button*>(wp)) != NULL )
447
+      if((mip = bp->mvalue()) != NULL)
448
+        ap->menuCallback(mip,(long int)data);
449
+}
450
+
451
+void app::_s_btn_cb(Fl_Widget* wp, long data )
452
+{
453
+  app*             ap;
454
+
455
+  if((ap = _getApp(wp)) != NULL )
456
+    if( wp != NULL )
457
+      ap->btnCallback( static_cast<const Fl_Button*>(wp),data);
458
+}
459
+
460
+void app::_s_value_cb(     Fl_Widget* wp, long data)
461
+{
462
+  app*             ap;
463
+  Fl_Valuator*     vp;
464
+
465
+  if((ap = _getApp(wp)) != NULL )
466
+    if((vp = static_cast<Fl_Valuator*>(wp)) != NULL)
467
+      ap->valueCallback(vp,data);
468
+}
469
+
470
+void app::_s_input_cb(   Fl_Widget* wp, long data)
471
+{
472
+  app* ap;
473
+  Fl_Input* inp;
474
+
475
+  if((ap = _getApp(wp)) != NULL)
476
+    if((inp = static_cast<Fl_Input*>(wp)) != NULL )
477
+      ap->inputCallback(inp,data);
478
+}
479
+
480
+void app::_s_callback(Fl_Widget* wp, void* data)
481
+{ ((app*)data)->appCallback(wp); }
482
+
483
+void app::_s_idle_cb(void *data)
484
+{ 
485
+  app* thisPtr = (app*)data;
486
+
487
+  if( thisPtr->idleCallback() == false )
488
+    Fl::remove_idle(_s_idle_cb,data);
489
+}
490
+
491
+void app::_s_timer_cb(void* userPtr)
492
+{ 
493
+  app* thisPtr = (app*)userPtr;
494
+
495
+  if( thisPtr->timerCallback() )
496
+    Fl::repeat_timeout(thisPtr->_timerPeriodSecs,_s_timer_cb,userPtr);
497
+}
498
+
499
+void app::_s_print( void* userPtr, const char* text )
500
+{ ((app*)userPtr)->print(text); }
501
+
502
+
503
+void app::_create_tabs(int titleCnt, const char* titleArray[])
504
+{
505
+  // Create a tab view and added it to the upper splitter area
506
+  _tabs = new Fl_Tabs(_splt->container1->x(),_splt->container1->y(),_splt->container1->w(),_splt->container1->h());
507
+  _splt->container1->add(_tabs);
508
+
509
+  int tx,ty,th,tw,i;
510
+  _tabs->client_area(tx,ty,tw,th);
511
+
512
+  for(i=0; i<titleCnt; ++i)
513
+  {
514
+    _tabs->begin();
515
+    initializeTab(i,tx,ty,tw,th,titleArray[i]);
516
+    _tabs->end();
517
+  }
518
+  
519
+  // Create an empty tab group and make it resizable 
520
+  // to prevent the other tab groups from being resizable.
521
+  _tabs->begin();
522
+  _tabs->resizable(new Fl_Group(tx,ty+30,1,1));
523
+  _tabs->end();
524
+}
525
+
526
+app*   app::_getApp( Fl_Widget* w )
527
+{
528
+  // walk up the widget tree until the top widget is  found
529
+  Fl_Group* gp = w->parent();
530
+  while( gp->parent() != NULL )
531
+    gp=gp->parent();
532
+
533
+  // the user data for the top widget is a pointer app - as set in:  callback(_s_callback,this);
534
+  return (app*)gp->user_data();
535
+}
536
+
537
+cmRC_t  app::_s_print_queue_cb(void* userCbPtr, unsigned msgByteCnt, const void* msgDataPtr )
538
+{
539
+  app* ap = (app*)userCbPtr;
540
+  ap->_print((const char*)msgDataPtr);
541
+  return cmOkRC;
542
+}
543
+
544
+void app::_checkPrintQueue()
545
+{
546
+  while( cmTsMp1cMsgWaiting(_printqH) )
547
+    if( cmTsMp1cDequeueMsg(_printqH, NULL, 0) != kOkThRC )
548
+      error("Print dequeue failed.");
549
+}
550
+
551
+void app::_print( const char* text )
552
+{
553
+  if( _con != NULL )
554
+    _con->insert(text);
555
+}

+ 119
- 0
src/cmflapp/app.h View File

@@ -0,0 +1,119 @@
1
+#ifndef app_h
2
+#define app_h
3
+
4
+class Fl_HSplitter;
5
+class Fl_Text_Buffer;
6
+class Fl_Text_Display;
7
+class Fl_Box;
8
+class Fl_Tabs;
9
+struct Fl_Menu_Item;
10
+class Fl_Menu_Bar;
11
+class Fl_Group;
12
+class Fl_Button;
13
+class Fl_Valuator;
14
+class Fl_Input;
15
+class drawWnd;
16
+
17
+class app : public Fl_Double_Window
18
+{
19
+
20
+public:
21
+
22
+  // widget id's for widgets created by createControls()
23
+  enum
24
+  {
25
+    kFileOpenMId,
26
+    kFileNewMId,
27
+    kEditCopyMId,
28
+    kEditPasteMId,
29
+
30
+    kBtn1MId,
31
+    kBtn2MId,
32
+    kBtn3MId,
33
+
34
+    kMenuBtn1MId,
35
+    kMenuBtn2MId,
36
+
37
+    kValue1MId,
38
+    kValue2MId,
39
+
40
+    kInput1MId
41
+  };
42
+
43
+  app(cmCtx_t* ctx, cmTsMp1cH_t printqH, int w, int h, const char *l, int argc, char *argv[]);
44
+  virtual ~app();
45
+
46
+  // Example tabbed window initialization example function 
47
+  // which also demonstrates some widgets
48
+  void createControls(Fl_Group* grp);
49
+
50
+  // called once from app() to initialize each tabbed window
51
+  virtual void initializeTab(int tabIndex, int x, int y, int w, int h, const char* label);
52
+
53
+  // Create the application menu
54
+  virtual void createMenu( int menuWidth, int menuHeight ); 
55
+
56
+  // Widget type specific callbacks
57
+  virtual void menuCallback( const Fl_Menu_Item* ip, long int id ); // menu and menu btn callback
58
+  virtual void btnCallback(  const Fl_Button*    bp, int id ); // btn callback
59
+  virtual void valueCallback(const Fl_Valuator*  vp, int id ); // valuator callback
60
+  virtual void inputCallback(const Fl_Input*     ip, int id ); // text input callback
61
+
62
+  virtual void appCallback(Fl_Widget* wp);    // app event callback
63
+  virtual bool idleCallback();                // return false to stop callback
64
+  virtual bool timerCallback();               // return false to stop callback
65
+
66
+  void error( const char* fmt, ... ); // report on error
67
+  
68
+  // print to the console
69
+  virtual void vprint( const char* fmt, va_list vl );
70
+  virtual void print( const char* fmt, ... ); 
71
+
72
+protected:
73
+  enum
74
+  {
75
+    kStatusH = 30,
76
+    kMenuH   = 30,
77
+    kCtlH    = 30
78
+  };
79
+
80
+  // static callbacks
81
+  static void _s_menu_cb(    Fl_Widget* wp, void* data);  // menu item callback
82
+  static void _s_menu_btn_cb(Fl_Widget* wp, void* data);  // menu btn callback
83
+  static void _s_btn_cb(     Fl_Widget* wp, long data);   // button callback
84
+  static void _s_value_cb(   Fl_Widget* wp, long data);   // value input or slider callback
85
+  static void _s_input_cb(   Fl_Widget* wp, long data);   // text input callback
86
+  static void _s_callback(   Fl_Widget* wp, void* data);  // main app callback
87
+  
88
+  static void _s_idle_cb(  void* data);    // idle callback
89
+  static void _s_timer_cb( void* userPtr); // timer callback
90
+  static void _s_print(    void* userPtr, const char* text ); // print text to the console
91
+
92
+  void _create_tabs(int titleCnt, const char* titleArray[]);
93
+
94
+  // walk down the widget tree until the app (root) widget is located
95
+  static app* _getApp( Fl_Widget* w );
96
+
97
+  // called internally by cmTsQueueDequeue() to send text to _print()
98
+  static cmRC_t _s_print_queue_cb(void* userCbPtr, unsigned msgByteCnt, const void* msgDataPtr );
99
+
100
+  // called periodically to check the print queue for waiting text.
101
+  void        _checkPrintQueue();
102
+
103
+  // send a string of text directly to the output console window
104
+  void        _print( const char* text );
105
+
106
+  double _timerPeriodSecs; // repeat period for the timer callback
107
+
108
+  cmCtx_t*          _ctx;   //
109
+  Fl_HSplitter*     _splt;  // main splitter window
110
+  Fl_Text_Buffer*   _buf;   // text buffer used by _con
111
+  Fl_Text_Display*  _con;   // text console output window
112
+  Fl_Tabs*          _tabs;  // tabs window
113
+  Fl_Menu_Bar*      _menu;  // app. menu
114
+  drawWnd*          _draw;  // custom widget
115
+  cmTsMp1cH_t       _printqH; // thread-safe queue for controlling access to the output console from multiple threads
116
+  int               _printFl; // used to prevent recursion due to throwing printing error
117
+};
118
+
119
+#endif

+ 24
- 0
src/cmflapp/appErr.h View File

@@ -0,0 +1,24 @@
1
+#ifndef appErr_h
2
+#define appErr_h
3
+
4
+#ifdef __cplusplus
5
+extern "C" {
6
+#endif
7
+
8
+enum
9
+{
10
+  kOkAppRC,
11
+  kQueueFailAppRC,
12
+  kFileSysFailAppRC,
13
+  kMemFailAppRC,
14
+  kTextSysFailAppRC,
15
+  kPrefsFailAppRC
16
+};
17
+
18
+  typedef unsigned cmAppRC_t;
19
+
20
+#ifdef __cplusplus
21
+}
22
+#endif
23
+
24
+#endif

+ 110
- 0
src/cmflapp/main.cpp View File

@@ -0,0 +1,110 @@
1
+#include <FL/Fl.H>
2
+#include <Fl/fl_draw.H>
3
+#include <FL/Fl_Double_Window.H>
4
+
5
+#include "cmPrefix.h"
6
+#include "cmGlobal.h"
7
+#include "cmFloatTypes.h"
8
+#include "cmRpt.h"
9
+#include "cmErr.h"
10
+#include "cmCtx.h"
11
+#include "cmMem.h"
12
+#include "cmMallocDebug.h"
13
+#include "cmLinkedHeap.h"
14
+#include "cmThread.h"
15
+#include "cmFileSys.h"
16
+#include "cmText.h"
17
+
18
+#include "appErr.h"
19
+#include "app.h"
20
+
21
+
22
+
23
+
24
+void print( void*, const cmChar_t* text)
25
+{ puts(text); }
26
+
27
+cmRC_t  print_queue_cb(void* userCbPtr, unsigned msgByteCnt, const void* msgDataPtr )
28
+{
29
+  print(NULL,(const char*)msgDataPtr);
30
+  return cmOkRC;
31
+}
32
+
33
+
34
+int main( int argc, char* argv[] )
35
+{
36
+  cmCtx_t     ctx;
37
+  cmTsMp1cH_t printqH         = cmTsMp1cNullHandle;
38
+  int         appWndW         = 1000;
39
+  int         appWndH         = 750;
40
+  const char* appPrefDir      = "gv";
41
+  const char* appTitle        = "GV Console";
42
+  bool        memDebugFl      = cmDEBUG_FL;
43
+  unsigned    memPadByteCnt   = memDebugFl ? 8 : 0;
44
+  unsigned    memAlignByteCnt = 16;
45
+  unsigned    memFlags        = memDebugFl ? (kTrackMmFl | kDeferFreeMmFl | kFillUninitMmFl) : 0;
46
+
47
+  cmCtxSetup(&ctx,appTitle,print,print,NULL,memPadByteCnt,memAlignByteCnt,memFlags);
48
+
49
+  // initialize the memory mgr
50
+  if(cmMdInitialize( memPadByteCnt, memAlignByteCnt, memFlags, &ctx.rpt ) != kOkMmRC )
51
+  {
52
+    cmErrMsg(&ctx.err,kMemFailAppRC,"Heap initialization failed.");
53
+    goto errLabel;
54
+  }
55
+
56
+  // initialize the file system
57
+  if( cmFsInitialize( &ctx, appPrefDir ) != kOkFsRC )
58
+    cmErrMsg(&ctx.err,kFileSysFailAppRC,"File system initialization failed.");
59
+
60
+  // initialize the text system
61
+  if( cmTsInitialize(&ctx) != kOkTxRC )
62
+    cmErrMsg(&ctx.err,kTextSysFailAppRC,"Text system initialization failed.");
63
+
64
+  // create the print queue
65
+  if( cmTsMp1cCreate( &printqH, 8192, print_queue_cb, NULL, NULL ) != kOkThRC )
66
+    cmErrMsg(&ctx.err,kQueueFailAppRC,"Print queue creation failed.");
67
+
68
+
69
+  if( cmErrLastRC(&ctx.err) == kOkAppRC )
70
+  {
71
+    app proj(&ctx, printqH, appWndW, appWndH, appTitle, argc, argv);
72
+    Fl::run();
73
+
74
+    // reset the pgm context and print queue  console output to stdout
75
+    cmRptSetup(&ctx.rpt,print,print,NULL);
76
+    cmTsMp1cSetCbFunc(printqH, print_queue_cb, NULL );
77
+  }
78
+
79
+  // empty any pending text to stdout
80
+  while( cmTsMp1cMsgWaiting(printqH) )
81
+    if( cmTsMp1cDequeueMsg(printqH, NULL, 0) != kOkThRC )
82
+      cmErrMsg(&ctx.err,kQueueFailAppRC,"Print dequeue failed.");
83
+
84
+  // destroy the print queue
85
+  if( cmTsMp1cDestroy(&printqH) != kOkThRC )
86
+    cmErrMsg(&ctx.err,kQueueFailAppRC,"Print queue destroy failed.");
87
+
88
+  // finalize the text system
89
+  if( cmTsFinalize() != kOkTxRC )
90
+    cmErrMsg(&ctx.err,kTextSysFailAppRC,"Text system finalization failed.");
91
+
92
+  // finalize the file system
93
+  if( cmFsFinalize() != kOkFsRC )
94
+    cmErrMsg(&ctx.err,kFileSysFailAppRC,"File system finalize failed.");
95
+
96
+  // report memory mgr errors
97
+  if( cmMdIsValid() )
98
+    cmMdReport( kIgnoreNormalMmFl );
99
+
100
+  // finalize the memory manager
101
+  if( cmMdFinalize() != kOkMmRC )
102
+    cmErrMsg(&ctx.err,kMemFailAppRC,"Heap finalization failed.");
103
+
104
+ errLabel:
105
+
106
+
107
+  
108
+
109
+  return 0;
110
+}

+ 0
- 39
src/proj/main.c View File

@@ -1,39 +0,0 @@
1
-#include "cmPrefix.h"
2
-#include "cmGlobal.h"
3
-#include "cmRpt.h"
4
-#include "cmErr.h"
5
-#include "cmCtx.h"
6
-#include "cmMem.h"
7
-#include "cmMallocDebug.h"
8
-#include "cmLinkedHeap.h"
9
-#include "cmFileSys.h"
10
-#include "cmText.h"
11
-
12
-void print( void* arg, const char* text )
13
-{
14
-  printf("%s\n",text);
15
-}
16
-
17
-int main( int argc, char* argv[] )
18
-{
19
-    // initialize the heap check library
20
-  bool       memDebugFl          = cmDEBUG_FL;
21
-  unsigned   memGuardByteCnt     = memDebugFl ? 8 : 0;
22
-  unsigned   memAlignByteCnt     = 16;
23
-  unsigned   memFlags            = memDebugFl ? kTrackMmFl | kDeferFreeMmFl | kFillUninitMmFl : 0;
24
-
25
-  cmCtx_t    ctx;
26
-  cmCtxSetup(&ctx,"cm test",print,print,NULL,memGuardByteCnt,memAlignByteCnt,memFlags);
27
-
28
-  cmMdInitialize( memGuardByteCnt, memAlignByteCnt, memFlags, &ctx.rpt );
29
-
30
-  cmFsInitialize( &ctx, "cm_test" );
31
-
32
-  cmTsInitialize(&ctx );
33
-
34
-  cmTsFinalize();
35
-  cmFsFinalize();
36
-  cmMdReport( kIgnoreNormalMmFl );
37
-  cmMdFinalize();
38
-  return 0;
39
-}

Loading…
Cancel
Save