| 1 | // ==================================================================== // |
|---|
| 2 | // // |
|---|
| 3 | // File : awt_advice.cpp // |
|---|
| 4 | // Purpose : // |
|---|
| 5 | // // |
|---|
| 6 | // // |
|---|
| 7 | // Coded by Ralf Westram (coder@reallysoft.de) in May 2002 // |
|---|
| 8 | // Copyright Department of Microbiology (Technical University Munich) // |
|---|
| 9 | // // |
|---|
| 10 | // Visit our web site at: http://www.arb-home.de/ // |
|---|
| 11 | // // |
|---|
| 12 | // // |
|---|
| 13 | // ==================================================================== // |
|---|
| 14 | |
|---|
| 15 | #include <stdlib.h> |
|---|
| 16 | #include <string.h> |
|---|
| 17 | |
|---|
| 18 | #include "awt_advice.hxx" |
|---|
| 19 | #include "awt.hxx" |
|---|
| 20 | |
|---|
| 21 | |
|---|
| 22 | using namespace std; |
|---|
| 23 | |
|---|
| 24 | #define AWAR_ADVICE_TMP "/tmp/advices/" |
|---|
| 25 | |
|---|
| 26 | #define AWAR_ADVICE_TEXT AWAR_ADVICE_TMP "text" |
|---|
| 27 | #define AWAR_ADVICE_UNDERSTOOD AWAR_ADVICE_TMP "understood" |
|---|
| 28 | |
|---|
| 29 | #define AWAR_ADVICE_DISABLED "/advices/disabled" |
|---|
| 30 | |
|---|
| 31 | // ------------------------- |
|---|
| 32 | // internal data : |
|---|
| 33 | // ------------------------- |
|---|
| 34 | |
|---|
| 35 | static bool initialized = false; |
|---|
| 36 | static AW_root *advice_root = 0; |
|---|
| 37 | static AW_default advice_props = 0; |
|---|
| 38 | |
|---|
| 39 | // -------------------------------------------------------- |
|---|
| 40 | |
|---|
| 41 | void init_Advisor(AW_root *awr, AW_default def) |
|---|
| 42 | { |
|---|
| 43 | awt_assert(!initialized); // can't init twice |
|---|
| 44 | |
|---|
| 45 | advice_root = awr; |
|---|
| 46 | advice_props = def; |
|---|
| 47 | |
|---|
| 48 | advice_root->awar_string(AWAR_ADVICE_TEXT, "<no advice>", advice_props); |
|---|
| 49 | advice_root->awar_int(AWAR_ADVICE_UNDERSTOOD, 0, advice_props); |
|---|
| 50 | |
|---|
| 51 | initialized = true; |
|---|
| 52 | } |
|---|
| 53 | |
|---|
| 54 | // ---------------------------- |
|---|
| 55 | // disabled advices : |
|---|
| 56 | // ---------------------------- |
|---|
| 57 | |
|---|
| 58 | static AW_awar *get_disabled_advices() { |
|---|
| 59 | return advice_root->awar_string(AWAR_ADVICE_DISABLED, "", advice_props); |
|---|
| 60 | } |
|---|
| 61 | |
|---|
| 62 | static bool advice_disabled(const char* id, AW_awar *var = 0) { |
|---|
| 63 | if (!var) var = get_disabled_advices(); |
|---|
| 64 | char *disabled_list = var->read_string(); |
|---|
| 65 | bool is_disabled = strstr(disabled_list, GBS_global_string(";%s;", id)) != 0; |
|---|
| 66 | free(disabled_list); |
|---|
| 67 | return is_disabled; |
|---|
| 68 | } |
|---|
| 69 | static void disable_advice(const char* id) { |
|---|
| 70 | AW_awar *var = get_disabled_advices(); |
|---|
| 71 | if (!advice_disabled(id, var)) { |
|---|
| 72 | char *disabled_list = var->read_string(); |
|---|
| 73 | if (strlen(disabled_list)) var->write_string(GBS_global_string("%s%s;", disabled_list, id)); |
|---|
| 74 | else var->write_string(GBS_global_string(";%s;", id)); |
|---|
| 75 | free(disabled_list); |
|---|
| 76 | } |
|---|
| 77 | } |
|---|
| 78 | |
|---|
| 79 | // ------------------------------------------- |
|---|
| 80 | |
|---|
| 81 | static void advice_close_cb(AW_window *aww, AW_CL cl_id, AW_CL type) { |
|---|
| 82 | int understood = advice_root->awar(AWAR_ADVICE_UNDERSTOOD)->read_int(); |
|---|
| 83 | |
|---|
| 84 | // switch to 'not understood'. Has to be checked by user for each advice. |
|---|
| 85 | advice_root->awar(AWAR_ADVICE_UNDERSTOOD)->write_int(0); |
|---|
| 86 | aww->hide(); |
|---|
| 87 | |
|---|
| 88 | if (understood) { |
|---|
| 89 | const char *id = (const char *)cl_id; |
|---|
| 90 | |
|---|
| 91 | disable_advice(id); |
|---|
| 92 | if (type & AWT_ADVICE_TOGGLE) { |
|---|
| 93 | static bool in_advice = false; |
|---|
| 94 | if (!in_advice) { |
|---|
| 95 | in_advice = true; |
|---|
| 96 | AWT_advice("You have disabled an advice.\n" |
|---|
| 97 | "In order to disable it PERMANENTLY, save properties.", AWT_ADVICE_TOGGLE); |
|---|
| 98 | in_advice = false; |
|---|
| 99 | } |
|---|
| 100 | } |
|---|
| 101 | } |
|---|
| 102 | } |
|---|
| 103 | static void advice_hide_and_close_cb(AW_window *aww, AW_CL cl_id, AW_CL type) { |
|---|
| 104 | advice_root->awar(AWAR_ADVICE_UNDERSTOOD)->write_int(1); |
|---|
| 105 | advice_close_cb(aww, cl_id, type); |
|---|
| 106 | } |
|---|
| 107 | |
|---|
| 108 | // ------------------------------------------- |
|---|
| 109 | |
|---|
| 110 | void AWT_reactivate_all_advices() { |
|---|
| 111 | AW_awar *awar_disabled = get_disabled_advices(); |
|---|
| 112 | |
|---|
| 113 | char *disabled = awar_disabled->read_string(); |
|---|
| 114 | char *nosemi = GBS_string_eval(disabled, ";=", NULL); |
|---|
| 115 | int entries = strlen(disabled)-strlen(nosemi); |
|---|
| 116 | |
|---|
| 117 | if (entries>0) { |
|---|
| 118 | awt_assert(entries>1); |
|---|
| 119 | entries--; |
|---|
| 120 | aw_message(GBS_global_string("Enabled %i advices", entries)); |
|---|
| 121 | } |
|---|
| 122 | else { |
|---|
| 123 | aw_message("No advices were disabled yet."); |
|---|
| 124 | } |
|---|
| 125 | |
|---|
| 126 | free(nosemi); |
|---|
| 127 | free(disabled); |
|---|
| 128 | |
|---|
| 129 | awar_disabled->write_string(""); |
|---|
| 130 | } |
|---|
| 131 | |
|---|
| 132 | void AWT_advice(const char *message, int type, const char *title, const char *corresponding_help) { |
|---|
| 133 | awt_assert(initialized); |
|---|
| 134 | size_t message_len = strlen(message); awt_assert(message_len>0); |
|---|
| 135 | long crc32 = GB_checksum(message, message_len, true, " .,-!"); // checksum is used to test if advice was shown |
|---|
| 136 | char *advice_id = GBS_global_string_copy("%lx", crc32); // do not delete (bound to cbs) |
|---|
| 137 | |
|---|
| 138 | bool show_advice = !advice_disabled(advice_id); |
|---|
| 139 | |
|---|
| 140 | if (show_advice) { |
|---|
| 141 | AW_awar *understood = advice_root->awar(AWAR_ADVICE_UNDERSTOOD); |
|---|
| 142 | understood->write_int(0); |
|---|
| 143 | |
|---|
| 144 | if (corresponding_help) type = AWT_Advice_Type(type|AWT_ADVICE_HELP); |
|---|
| 145 | #if defined(ASSERTION_USED) |
|---|
| 146 | else awt_assert((type & AWT_ADVICE_HELP) == 0); |
|---|
| 147 | #endif // ASSERTION_USED |
|---|
| 148 | |
|---|
| 149 | AW_window_simple *aws = new AW_window_simple; // do not delete (ARB will crash) -- maybe reuse window for all advices? |
|---|
| 150 | |
|---|
| 151 | if (!title) title = "Please read carefully"; |
|---|
| 152 | aws->init(advice_root, "advice", GBS_global_string("ARB: %s", title)); |
|---|
| 153 | aws->load_xfig("awt/advice.fig"); |
|---|
| 154 | |
|---|
| 155 | bool has_help = type & AWT_ADVICE_HELP; |
|---|
| 156 | bool help_pops_up = false; |
|---|
| 157 | |
|---|
| 158 | if (has_help) { |
|---|
| 159 | aws->callback( AW_POPUP_HELP,(AW_CL)corresponding_help); |
|---|
| 160 | aws->at("help"); |
|---|
| 161 | aws->create_button(0, "HELP","H"); |
|---|
| 162 | |
|---|
| 163 | if (type & AWT_ADVICE_HELP_POPUP) help_pops_up = true; |
|---|
| 164 | } |
|---|
| 165 | |
|---|
| 166 | aws->at("advice"); |
|---|
| 167 | aws->create_text_field(AWAR_ADVICE_TEXT); |
|---|
| 168 | |
|---|
| 169 | advice_root->awar(AWAR_ADVICE_TEXT) |
|---|
| 170 | ->write_string(has_help && !help_pops_up |
|---|
| 171 | ? GBS_global_string("%s\n\nPlease refer to 'HELP' for more info.", message) |
|---|
| 172 | : message); |
|---|
| 173 | |
|---|
| 174 | if (help_pops_up) AW_POPUP_HELP(aws, (AW_CL)corresponding_help); |
|---|
| 175 | |
|---|
| 176 | if (type & AWT_ADVICE_TOGGLE) { |
|---|
| 177 | aws->label("Do not advice me again"); |
|---|
| 178 | aws->at("understood"); |
|---|
| 179 | aws->create_toggle(AWAR_ADVICE_UNDERSTOOD); |
|---|
| 180 | } |
|---|
| 181 | |
|---|
| 182 | aws->at("ok"); |
|---|
| 183 | if (type & AWT_ADVICE_TOGGLE) { |
|---|
| 184 | aws->callback(advice_close_cb, (AW_CL)advice_id, type); |
|---|
| 185 | aws->create_button(0, "OK", "O"); |
|---|
| 186 | } |
|---|
| 187 | else { |
|---|
| 188 | aws->callback(advice_hide_and_close_cb, (AW_CL)advice_id, type); |
|---|
| 189 | aws->create_autosize_button(0, "I understand", "O", 2); |
|---|
| 190 | } |
|---|
| 191 | |
|---|
| 192 | aws->window_fit(); |
|---|
| 193 | aws->show(); |
|---|
| 194 | } |
|---|
| 195 | } |
|---|