File: window.hh

package info (click to toggle)
cadabra 1.46-6
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 5,244 kB
  • sloc: cpp: 33,188; ansic: 2,724; makefile: 329; yacc: 180; sh: 157; python: 45; lex: 38; lisp: 19
file content (453 lines) | stat: -rw-r--r-- 16,417 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
/* 

	Cadabra: a field-theory motivated computer algebra system.
	Copyright (C) 2001-2011  Kasper Peeters <kasper.peeters@aei.mpg.de>

   This program 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 3 of the
   License, or (at your option) any later version.

   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 
*/

#ifndef window_hh__
#define window_hh__

#include <gtkmm/main.h>
#include <gtkmm/actiongroup.h>
#include <gtkmm/radioaction.h>
#include <gtkmm/uimanager.h>
#include <gtkmm/button.h>
#include <gtkmm/window.h>
#include <gtkmm/box.h>
#include <gtkmm/statusbar.h>
#include <gtkmm/textview.h>
#include <gtkmm/treeview.h>
#include <gtkmm/notebook.h>
#include <gtkmm/optionmenu.h>
#include <gtkmm/treestore.h>
#include <gtkmm/textbuffer.h>
#include <gtkmm/scrolledwindow.h>
#include <gtkmm/separator.h>
#include <gtkmm/menu.h>
#include <gtkmm/menubar.h>
#include <gtkmm/image.h>
#include <gtkmm/eventbox.h>
#include <gtkmm/expander.h>
#include <gtkmm/stock.h>
#include <gtkmm/paned.h>
#include <gtkmm/progressbar.h>
#include <gdkmm.h>
#include <modglue/main.hh>
#include <modglue/pipe.hh>
#include <modglue/ext_process.hh>

#include <stack>

#include "widgets.hh"
#include "help.hh"

class XCadabra;

/// A DataCell contains the information required to display a 
/// cell, but not the actual widget. Therefore, multiple widgets
/// can read from the data stored in this cell; multiple notebook
/// canvasses can therefore display the same notebook data.
///
/// DataCells are stored on the heap and reference counted since there
/// are too many objects with a pointer to them to keep track of 
/// proper de-allocation manually.

class DataCell : public Glib::Object {
	public:
		enum cell_t { c_input, c_output, c_comment, c_texcomment, c_tex, c_error };

		DataCell(cell_t, const std::string& str="", bool texhidden=false);

		cell_t                        cell_type;
		Glib::RefPtr<Gtk::TextBuffer> textbuf;
		Glib::RefPtr<TeXBuffer>       texbuf;
		std::string                   cdbbuf;             // c_output only: the output in cadabra input format
		bool                          tex_hidden;         // c_tex only
		bool                          sensitive;
		int                           sectioning;         // >0 for section header cells
		bool                          running;
};


/// A VisualCell contains pointers to the various cell widgets,
/// which in turn contain pointers to DataCell objects.

class VisualCell {
	public:
		union {
				ExpressionInput *inbox;
				TeXView         *outbox;
				TeXInput        *texbox;
		};
		Glib::RefPtr<DataCell> datacell;
};

/// The Action object is used to pass user action instructions around
/// and store them in the undo/redo stacks. All references to cells is
/// in terms of smart pointers to DataCells. 
///
/// This requires that if we delete a cell, its data cell together
/// with any TextBuffer and TeXBuffer objects should be kept in
/// memory, so that the pointer remains valid.  We keep a RefPtr.

class ActionBase : public Glib::Object {
	public:
		ActionBase(Glib::RefPtr<DataCell>);

		virtual void execute(XCadabra&)=0;
		virtual void revert(XCadabra&)=0;

		Glib::RefPtr<DataCell> cell;
};

/// As a general rule, objects derived from ActionBase are friends of XCadabra, 
/// so they really should be thought of as bits of functionality split off from
/// that large class.

class ActionAddCell : public ActionBase {
	public:
		ActionAddCell(Glib::RefPtr<DataCell>, Glib::RefPtr<DataCell> ref_, bool before_);

		/// Executing will also show the cell and grab its focus.
		virtual void execute(XCadabra&);
		virtual void revert(XCadabra&);

	private:
		// Keep track of the location where this cell is inserted into
		// the notebook. 
		Glib::RefPtr<DataCell> ref;
		bool                   before;
		std::vector<Glib::RefPtr<DataCell> > associated_cells; // output and comment cells
};

class ActionRemoveCell : public ActionBase {
	public:
		ActionRemoveCell(Glib::RefPtr<DataCell>);
		~ActionRemoveCell();

		virtual void execute(XCadabra&);
		virtual void revert(XCadabra&);

	private:
		// Keep track of the location where this cell was in the notebook. Since it is
		// not possible to delete the first cell, it is safe to keep a reference to the
		// cell just before the one we are deleting. 
		// Note that since we keep a RefPtr to this datacell, that cell will stay alive
		// even when a subsequent action will remove it. 
		Glib::RefPtr<DataCell>               prev_cell; 
		std::vector<Glib::RefPtr<DataCell> > associated_cells; // output and comment cells
};

class ActionAddText : public ActionBase {
	public:
		ActionAddText(Glib::RefPtr<DataCell>, int, const std::string&);

		virtual void execute(XCadabra&);
		virtual void revert(XCadabra&);
		
		int         insert_pos;
		std::string text;
};

class ActionRemoveText : public ActionBase {
	public:
		ActionRemoveText(Glib::RefPtr<DataCell>, int, int, const std::string&);

		virtual void execute(XCadabra&);
		virtual void revert(XCadabra&);

		int from_pos, to_pos;
		std::string removed_text;
};

typedef std::stack<Glib::RefPtr<ActionBase> > ActionStack;


/// NotebookCanvas is a view on notebook data. Any number of these
/// may be instantiated, and they all reflect the current status
/// of the document stored in the master XCadabra class.

class NotebookCanvas : public Gtk::VPaned {
	public:
		NotebookCanvas(XCadabra& doc);
		~NotebookCanvas();

//		bool handle_expression_input(std::string str);
//		bool handle_tex_update(const std::string&);
//		bool receive_output(std::string eqno, std::string eq);
//		bool receive_comment(std::string comment);

		bool handle_key_press_event(GdkEventKey*);

		/// Add a VisualCell corresponding to the given DataCell.
		/// The second and third element determine the position relative
		/// to another DataCell (or, by default, relative to the end marker).
		VisualCell* add_cell(Glib::RefPtr<DataCell>, Glib::RefPtr<DataCell> ref, bool before=true);
		
		void show_cell(Glib::RefPtr<DataCell>);

		/// Remove a VisualCell corresponding to the given DataCell.
		void         remove_cell(Glib::RefPtr<DataCell>);
		/// Make a cell grab focus. This will trigger a run of this cell, with various
		/// other side-effects before it returns.
		void         cell_grab_focus(VisualCell *);
		void         cell_grab_focus(Glib::RefPtr<DataCell>);
		void         select_first_input_cell();
		virtual void show();

//		void         scroll_to(Gtk::Allocation al);
		void         redraw_cells();
		bool         scroll_into_view_callback(VisualCell *);
		bool         scroll_into_view(VisualCell *, bool center=false);
		bool         scroll_into_view(Glib::RefPtr<DataCell>, bool center=false);
		void         scroll_to_start();
		void         scroll_to_end();
		void         scroll_up();
		void         scroll_down();

		XCadabra&                 doc;
		typedef std::list<VisualCell *> VisualCells_t;
		VisualCells_t             visualcells; // managed here
		Gtk::EventBox             ebox;
 		Gtk::ScrolledWindow       scroll;
		Gtk::VBox                 scrollbox;
		Gtk::HSeparator           bottomline;
};


/// Each notebook has one cadabra process associated to it, and one
/// main window to control it. 

class XCadabra : public Gtk::Window {
	public:
		XCadabra(modglue::ext_process&, const std::string& filename, modglue::main *);
		virtual ~XCadabra();

		/// Data coming from cadabra arrives here. This handles
		/// adding boxes to the document and propagating this to the
		/// notebooks.
		bool receive(modglue::ipipe& p);
		bool receive_err(modglue::ipipe& p);
		std::string accumulated_error;

		/// Data from the NotebookCanvas objects arrives here.
		bool handle_editbox_output(std::string str, NotebookCanvas *, VisualCell *);
		void on_my_insert(const Gtk::TextIter& pos, const Glib::ustring& text, int bytes, Glib::RefPtr<DataCell>);
		void on_my_erase(const Gtk::TextIter& start, const Gtk::TextIter& end, Glib::RefPtr<DataCell>);

		/// Events from the notebook cells arrive here.
		void handle_on_grab_focus(NotebookCanvas *, VisualCell *);
		bool handle_visibility_toggle(GdkEventButton *, NotebookCanvas *, VisualCell *);
		bool handle_outbox_select(GdkEventButton *, NotebookCanvas *, VisualCell *);
		bool handle_tex_update_request(std::string, NotebookCanvas *, VisualCell *);

		/// Toplevel keyboard handling.
		virtual bool on_key_press_event(GdkEventKey *);

		/// All the menu routines.
		void on_file_new();
		void on_file_open();
		void on_file_save();
		void on_file_save_as();
		void on_file_print();
		void on_file_export_text();
		void on_file_quit();
		bool quit_safeguard(bool quit=true);
		void on_edit_copy();
		void on_edit_paste();
		void on_edit_insert_tex_above();
		void on_edit_insert_tex_below();
		void on_edit_insert_input_above();
		void on_edit_insert_input_below();
		void on_edit_insert_section_above();
		void on_edit_remove_cell();
		void on_edit_divide_cell();
		void on_view_split();
		void on_view_close();
		void on_settings_font_size(int);
		void on_settings_brain(int);
		void on_tutorial_open(unsigned int);
		void on_help_about();
		void on_help_citing();
		void on_help_properties(const std::string&);
		void on_help_algorithms(const std::string&);
		void on_help_reserved(const std::string&);
		bool on_autocomplete();
		void on_help_context();
		void on_stop();
		void on_kill();
		void on_run();
		void on_run_to();
		void on_run_from();

		bool current_objtype_and_name(CadabraHelp::objtype_t&, std::string&);
		void insert_at_mark(const std::string instxt);

		/// Saving and loading to/from disk. If the return string is
		/// non-empty, it contains an error message.
		void clear();
		std::string save(const std::string&) const;
		std::string load(const std::string&, bool ignore_nonexistence=false); 
		std::string expo(const std::string&) const; 

		/// Handling starting/restarting of the kernel.
		bool on_kernel_exit(modglue::ext_process&);

		/// Clipboard handling
		void on_clipboard_get(Gtk::SelectionData&, guint info);
		void on_clipboard_clear();
		std::string clipboard_txt, clipboard_cdb;

		/// Adding and removing cells from the current document.
		/// These routines also update all NotebookCanvas objects
		/// so that they reflect the current structure of the document.
		/// The DataCell ownership is handled by the XCadabra class once
		/// it has been added here. 
		/// These functions do _not_ grab focus or make the new cell active.
		/// The add_cell member also does _not_ call show_cell: cells will not
		/// automatically become visible.
		Glib::RefPtr<DataCell> add_cell(Glib::RefPtr<DataCell>, Glib::RefPtr<DataCell> ref, bool before=true);

		/// Show the datacell in all canvasses.
		void         show_cell(Glib::RefPtr<DataCell>);

		/// Add another notebook canvas to the window.
		void         add_canvas();

		/// Call this to determine which cell will scroll into view as soon as the Gtk main loop
		/// regains control.
		void         set_next_into_view(VisualCell *);

		/// Signals from Gtk, such as closing windows or changing the text
		/// of an input cell.
		virtual bool on_delete_event(GdkEventAny*);
		virtual bool on_configure_event(GdkEventConfigure*);
		void         on_signal_exception();
		void         input_cell_modified();
		void         tex_cell_modified();


		/// Display of error messages.
		void         generic_error_popup(const std::string&) const;

		void         connect_io_signals();
		void         disconnect_io_signals();	

		int          font_step;
		int          brain_wired;
	private:
		/// Variables for the undo/redo mechanism.
		ActionStack      undo_stack, redo_stack;
		bool             disable_stacks; // for changes which should not be recorded on the stack
		bool             action_add(Glib::RefPtr<ActionBase>); // takes ownership and fills the stacks 
		void             action_undo();
		void             action_redo();

		/// Various assorted other variables related to communicating with the kernel.
		Gdk::Cursor      hglass;
		bool             load_file; // used by main to indicate a load should occur after start
		bool             have_received;
		modglue::main   *cmm;
		std::map<int, sigc::connection> connections;
		std::string      name;
		bool             modified;
		bool             running;
		Glib::RefPtr<DataCell> running_last;
		bool             restarting_kernel;
		bool             callmm(Glib::IOCondition, int fd);
		void             update_title();
		bool             make_backup(const std::string&) const;
		void             remove_noninput_below(Glib::RefPtr<DataCell>);
		void             kernel_idle();
		/// A map to keep track of identifiers of input cells. These are used to associated input
		/// data to the kernel to output data from the kernel, and hence can be used to associate
		/// the output to the right input cell.
		std::map<long, Glib::RefPtr<DataCell> > id_to_datacell;
		long             last_used_id;

		/// Boxes and widgets.
		std::vector<NotebookCanvas *>  canvasses;   // managed by gtk
		CadabraHelp                    help_window;
		NotebookCanvas                *active_canvas;
		VisualCell                    *active_cell;
		Gtk::VBox                      topbox;
		Gtk::HBox                      supermainbox;
		Gtk::VBox                      mainbox;
		Gtk::HBox                      buttonbox;
		Gtk::HBox                      statusbarbox;
		Gtk::VBox                      progressbarvbox;
		Gtk::ProgressBar               progressbar1,progressbar2;
		Glib::RefPtr<Gtk::ActionGroup> actiongroup;
		Glib::RefPtr<Gtk::Action>      undo_action_menu, redo_action_menu;
		Glib::RefPtr<Gtk::UIManager>   uimanager;
		Glib::RefPtr<Gtk::RadioAction> font_action0, font_action1, font_action2, font_action3;
		Glib::RefPtr<Gtk::RadioAction> brain_wired_action0, brain_wired_action1;
		Gtk::HBox                      statusbox;
		Gtk::Label                     b_cdbstatus, b_kernelversion;
		Gtk::Button                    b_kill, b_run, b_run_to, b_run_from, b_help, b_stop, b_undo, b_redo;
		int                            last_configure_width;

		/// Storage of document data. This data is not managed by smart
		/// pointers and should thus be deleted by the XCadabra
		/// destructor.
		/// The order in which pointers to datacells appear reflects the
		/// order in the document. We never use iterators directly in this
		/// list to refer to a cell (always use the RefPtr<DataCell> pointers).
		typedef std::list<Glib::RefPtr<DataCell> > DataCells_t;
		DataCells_t                   datacells;

		/// Data concerning the interaction with the externally started
		/// cadabra process.
		modglue::ext_process&     cdb;
		enum parse_mode_t         { m_status, m_eqno, m_eq, m_property, m_algorithm, m_reserved,
											 m_discard, m_comment, m_texcomment, m_error,
		                            m_progress, m_plain };
		std::vector<parse_mode_t> parse_mode;
		std::string               eqno, eq, status, progress, plain, algorithm, property, reserved;
		int                       progress_todo, progress_done, progress_count;

		/// Collection of all known algorithm and property names, as extracted from the kernel.
		void add_property_help(const std::string&);
		void add_algorithm_help(const std::string&);
		void add_reserved_help(const std::string&);
		std::set<std::string> property_set, algorithm_set;
		static const char * const autocomplete_strings[];
		std::string duplicate_underscores(const std::string& str) const;

		/// Cut-n-paste data
		VisualCell  *selected;

		/// Configuration data saving/loading
		std::string save_config() const;
		std::string load_config();

		TeXEngine tex_engine;

		friend class ActionRemoveCell;
		friend class ActionAddCell;

		/// When the main loop is idle, this function will get called and will check
		/// all 'to_scroll_to' cells of the canvasses.
		bool         on_idle();

		/// Cell to scroll into view as soon as the main loop is idle. 
		VisualCell  *to_scroll_to;
};


#endif