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
|