source: trunk/SL/MACROS/macro_gui.cxx

Last change on this file was 19489, checked in by westram, 15 months ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.0 KB
Line 
1// ============================================================= //
2//                                                               //
3//   File      : macro_gui.cxx                                   //
4//   Purpose   :                                                 //
5//                                                               //
6//   Coded by Ralf Westram (coder@reallysoft.de) in May 2005     //
7//   Institute of Microbiology (Technical University Munich)     //
8//   http://www.arb-home.de/                                     //
9//                                                               //
10// ============================================================= //
11
12#include "macros.hxx"
13#include "macros_local.hxx"
14#include "trackers.hxx"
15
16#include <arbdb.h>
17#include <arb_file.h>
18#include <arb_match.h>
19
20#include <aw_window.hxx>
21#include <aw_edit.hxx>
22#include <aw_file.hxx>
23#include <aw_awar.hxx>
24#include <aw_msg.hxx>
25#include <arbdbt.h>
26#include <ad_cb.h>
27
28#define ma_assert(bed) arb_assert(bed)
29
30#define AWAR_MACRO_RECORDING_MACRO_TEXT AWAR_MACRO_BASE "/button_label"
31#define AWAR_MACRO_RECORDING_EXPAND     AWAR_MACRO_BASE "/expand"
32#define AWAR_MACRO_RECORDING_RUNB4      AWAR_MACRO_BASE "/runb4"
33#define AWAR_MACRO_INTERRUPT_PROMPT     AWAR_MACRO_BASE "/" NEVER_RECORDED_ID "/prompt"
34
35static void delete_macro_cb(AW_window *aww) {
36    AW_root *awr       = aww->get_root();
37    char    *macroName = AW_get_selected_fullname(awr, AWAR_MACRO_BASE);
38
39    if (GB_unlink(macroName)<0) aw_message(GB_await_error());
40    else AW_refresh_fileselection(awr, AWAR_MACRO_BASE);
41
42    free(macroName);
43}
44
45static void macro_execution_finished(AW_root *awr, char *macroName) {
46#if defined(DEBUG)
47    fprintf(stderr, "macro_execution_finished(%s)\n", macroName);
48#endif
49
50    AW_set_selected_fullname(awr, AWAR_MACRO_BASE, macroName); // reset selected macro (needed if macro calls other macro(s))
51
52    free(macroName);
53}
54
55static void exec_macro_cb(AW_window *aww, bool loop_marked) {
56    AW_root  *awr       = aww->get_root();
57    char     *macroName = AW_get_selected_fullname(awr, AWAR_MACRO_BASE); // @@@ instead use function returning plain name w/o dir
58    GB_ERROR  error     = getMacroRecorder(awr)->execute(macroName, loop_marked, makeRootCallback(macro_execution_finished, macroName));
59    if (error) {
60        aw_message(error);
61        free(macroName); // only free in error-case (see macro_execution_finished)
62    }
63}
64
65inline void update_macro_record_button(AW_root *awr) {
66    awr->awar(AWAR_MACRO_RECORDING_MACRO_TEXT)->write_string(awr->is_tracking() ? "STOP" : "RECORD");
67}
68
69static void start_macro_cb(AW_window *aww) {
70    AW_root  *awr   = aww->get_root();
71    GB_ERROR  error = NULp;
72
73    if (awr->is_tracking()) {
74        error = getMacroRecorder(awr)->stop_recording();
75    }
76    else {
77        bool expand = awr->awar(AWAR_MACRO_RECORDING_EXPAND)->read_int();
78        bool runb4  = expand && awr->awar(AWAR_MACRO_RECORDING_RUNB4)->read_int();
79
80        char *macroName = AW_get_selected_fullname(awr, AWAR_MACRO_BASE);
81        if (GB_is_directory(macroName)) {
82            error = "Please specify name of macro to record";
83        }
84        else {
85            if (runb4) exec_macro_cb(aww, false);
86
87            char *sac = GBS_global_string_copy("%s/%s", aww->window_defaults_name, MACRO_RECORD_ID);
88            error = getMacroRecorder(awr)->start_recording(macroName, sac, expand);
89            free(sac);
90        }
91        free(macroName);
92    }
93
94    AW_refresh_fileselection(awr, AWAR_MACRO_BASE);
95    update_macro_record_button(awr);
96    if (error) aw_message(error);
97}
98
99static void insert_interruption_to_macro_cb(AW_window *aww) {
100    AW_root  *awr   = aww->get_root();
101    GB_ERROR  error = NULp;
102
103    if (!awr->is_tracking()) {
104        error = "Only possible while recording macro.";
105    }
106    else {
107        const char *text  = awr->awar(AWAR_MACRO_INTERRUPT_PROMPT)->read_char_pntr();
108        char       *info  = GBS_regreplace(text, "/\\s* //", &error);
109
110        if (!error) {
111            if (info[0] == 0) {
112                error = "Please insert some text as user prompt";
113            }
114            else {
115                getMacroRecorder(awr)->add_planned_interruption(text);
116            }
117        }
118
119        free(info);
120    }
121
122    aw_message_if(error);
123}
124
125static void popup_interrupt_macro_window_cb(AW_window *aww) {
126    AW_root *awr = aww->get_root();
127    if (!awr->is_tracking()) {
128        aw_message("Note: this will only work while recording a macro!");
129    }
130
131    static AW_window_simple *aws = NULp;
132    if (!aws) {
133        aws = new AW_window_simple;
134
135        aws->init(awr, "DEFINE_INTERRUPTION", "Define macro interruption");
136        aws->load_xfig("macro_interruption.fig");
137
138        aws->at("close"); aws->callback(AW_POPDOWN);
139        aws->create_button(NEVER_RECORDED_ID "CLOSE", "CLOSE", "C");
140
141        aws->at("help"); aws->callback(makeHelpCallback("macro_interruption.hlp"));
142        aws->create_button(NEVER_RECORDED_ID "HELP", "HELP", "H");
143
144        aws->at("box");
145        aws->create_text_field(AWAR_MACRO_INTERRUPT_PROMPT);
146
147        aws->at("add");
148        aws->callback(insert_interruption_to_macro_cb);
149        aws->create_autosize_button(NEVER_RECORDED_ID "Add", ".. and interrupt playback until user presses 'continue'");
150    }
151
152    aws->activate();
153}
154
155static void edit_macro_cb(AW_window *aww) {
156    char *path = AW_get_selected_fullname(aww->get_root(), AWAR_MACRO_BASE);
157    AW_edit(path);
158    free(path);
159}
160
161static void macro_recording_changed_cb() {
162    update_macro_record_button(AW_root::SINGLETON);
163}
164
165static void create_macro_variables(AW_root *aw_root) {
166    AW_create_fileselection_awars(aw_root, AWAR_MACRO_BASE, ".", ".amc", "");
167    aw_root->awar_string(AWAR_MACRO_RECORDING_MACRO_TEXT, "RECORD");
168    aw_root->awar_int(AWAR_MACRO_RECORDING_EXPAND, 0);
169    aw_root->awar_int(AWAR_MACRO_RECORDING_RUNB4, 0);
170    aw_root->awar_string(AWAR_MACRO_INTERRUPT_PROMPT, "");
171
172    {
173        UserActionTracker *tracker       = aw_root->get_tracker();
174        MacroRecorder     *macroRecorder = dynamic_cast<MacroRecorder*>(tracker);
175
176        GBDATA   *gb_main = macroRecorder->get_gbmain();
177        GB_ERROR  error   = NULp;
178
179        GB_transaction ta(gb_main);
180
181        GBDATA *gb_recording     = GB_searchOrCreate_int(gb_main, MACRO_TRIGGER_RECORDING, 0);
182        if (!gb_recording) error = GB_await_error();
183        else    error            = GB_add_callback(gb_recording, GB_CB_CHANGED, makeDatabaseCallback(macro_recording_changed_cb));
184
185        if (error) aw_message(GBS_global_string("Failed to bind macro_recording_changed_cb (Reason: %s)", error));
186    }
187
188    update_macro_record_button(aw_root);
189}
190
191static void popup_macro_window(AW_window *aww) {
192    static AW_window_simple *aws = NULp;
193    if (!aws) {
194        AW_root *aw_root = aww->get_root();
195
196        aws = new AW_window_simple;
197        aws->init(aw_root, MACRO_WINDOW_ID, "MACROS");
198        aws->load_xfig("macro_select.fig");
199
200        create_macro_variables(aw_root);
201
202        aws->at("close"); aws->callback(AW_POPDOWN);
203        aws->create_button("CLOSE", "CLOSE", "C");
204
205        aws->at("help"); aws->callback(makeHelpCallback("macro.hlp"));
206        aws->create_button("HELP", "HELP");
207
208        aws->at("record"); aws->callback(start_macro_cb);
209        aws->create_button(MACRO_RECORD_ID, AWAR_MACRO_RECORDING_MACRO_TEXT);
210
211        aws->at("expand"); aws->create_toggle(AWAR_MACRO_RECORDING_EXPAND);
212        aws->at("runb4");  aws->create_toggle(AWAR_MACRO_RECORDING_RUNB4);
213
214        aws->at("interrupt"); aws->callback(popup_interrupt_macro_window_cb);
215        aws->create_button(NEVER_RECORDED_ID, "Interrupt");
216
217        aws->at("edit");   aws->callback(edit_macro_cb);   aws->create_button("EDIT",   "EDIT");
218        aws->at("delete"); aws->callback(delete_macro_cb); aws->create_button("DELETE", "DELETE");
219
220        aws->at("exec");
221        aws->callback(makeWindowCallback(exec_macro_cb, false));
222        aws->create_button(MACRO_PLAYBACK_ID, "EXECUTE");
223
224        aws->at("execWith");
225        aws->callback(makeWindowCallback(exec_macro_cb, true));
226        aws->create_autosize_button(MACRO_PLAYBACK_MARKED_ID, "Execute with each marked species");
227
228        AW_create_fileselection(aws, AWAR_MACRO_BASE, "", "ARBMACROHOME^ARBMACRO", ANY_DIR, false);
229    }
230    aws->activate();
231}
232
233void insert_macro_menu_entry(AW_window *awm, bool prepend_separator) {
234    if (getMacroRecorder(awm->get_root())) {
235        if (prepend_separator) awm->sep______________();
236        awm->insert_menu_topic("macros", "Macros ", "M", "macro.hlp", AWM_ALL, popup_macro_window);
237    }
238}
239
240static void dont_announce_done(AW_root*) {}
241
242void execute_macro(AW_root *root, const char *macroname) {
243    // used to execute macro passed via CLI
244    GB_ERROR error = NULp;
245    {
246        // @@@ allow macro playback from client? (using server via AWAR)
247        MacroRecorder *recorder = getMacroRecorder(root);
248        if (!recorder) error    = "macro playback only available in server";
249        else           error    = recorder->execute(macroname, false, makeRootCallback(dont_announce_done));
250    }
251
252    if (error) {
253        aw_message(GBS_global_string("Can't execute macro '%s' (Reason: %s)", macroname, error));
254    }
255}
Note: See TracBrowser for help on using the repository browser.