1 | // ================================================================ // |
---|
2 | // // |
---|
3 | // File : ED4_seq_colors.cxx // |
---|
4 | // Purpose : Sequence foreground coloring. // |
---|
5 | // Viewing differences only. // |
---|
6 | // // |
---|
7 | // Institute of Microbiology (Technical University Munich) // |
---|
8 | // http://www.arb-home.de/ // |
---|
9 | // // |
---|
10 | // ================================================================ // |
---|
11 | |
---|
12 | #include "ed4_seq_colors.hxx" |
---|
13 | #include "ed4_class.hxx" |
---|
14 | |
---|
15 | #include <aw_root.hxx> |
---|
16 | #include <aw_awar.hxx> |
---|
17 | #include <aw_awar_defs.hxx> |
---|
18 | #include <aw_msg.hxx> |
---|
19 | #include <arbdbt.h> |
---|
20 | |
---|
21 | #include <cctype> |
---|
22 | |
---|
23 | static int default_NUC_set = 0; // number of default nucleotide set |
---|
24 | static int default_AMI_set = 3; // number of default amino acid set |
---|
25 | |
---|
26 | #define SEQ_COLOR_SETS 8 |
---|
27 | #define SEQ_COLOR_SET_ELEMS 28 // has to be a even number! |
---|
28 | |
---|
29 | #define AWAR_SEQ_PATH "awt/seq_colors/" |
---|
30 | #define AWAR_SEQ_NAME_STRINGS_TEMPLATE AWAR_SEQ_PATH "strings/elem_%i" |
---|
31 | #define AWAR_SEQ_NAME_TEMPLATE AWAR_SEQ_PATH "set_%i/elem_%i" |
---|
32 | #define AWAR_SEQ_NAME_SELECTOR_NA AWAR_SEQ_PATH "na/select" |
---|
33 | #define AWAR_SEQ_NAME_SELECTOR_AA AWAR_SEQ_PATH "aa/select" |
---|
34 | |
---|
35 | static const char *default_sets[SEQ_COLOR_SETS] = { |
---|
36 | //A B C D E F G H I J K L M N O P Q R S T U V W X Y Z * - |
---|
37 | "=2=0=3=0=0=0=4=0=0=0=0=0=0=6=0=0=0=0=0=5=5=0=0=0=0=0=0=6", // A, C, G, TU and N in 5 colors |
---|
38 | "R2=0Y3=0=0=0R2=0=0=0=0=0=0=0=0=0=0=2=0Y3Y3=0=0=0=3=0=0=6", // AG and CTU in 2 colors |
---|
39 | "=6=5=6=5=7=7=6=5=7=7=3=7=3=9=7=7=7=3=3=6=6=5=3=7=3=7=7=6", // ambiguity |
---|
40 | "=7=0=7=8=2=9=8=9=3=0=2=3=7=8=0=8=2=2=2=2=0=3=9=6=9=0=0=6", // Protein colors |
---|
41 | |
---|
42 | "=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=6", |
---|
43 | "o9=0|2=0=0=0o5=0=0=0=0=0=0=0=0=0=0=0=0|8|8=0=0=0=0=0=0=6", // ambiguity (symbols) |
---|
44 | "=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=6", |
---|
45 | "=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=6", |
---|
46 | }; |
---|
47 | |
---|
48 | static bool seq_color_awars_created = false; |
---|
49 | |
---|
50 | // -------------------------------------------------------------------------------- |
---|
51 | |
---|
52 | static const char *default_characters(int elem) { |
---|
53 | static char result[3] = "xX"; |
---|
54 | |
---|
55 | if (elem<26) { // first 26 elements (0-25) are characters |
---|
56 | result[0] = 'a'+elem; |
---|
57 | result[1] = 'A'+elem; |
---|
58 | } |
---|
59 | else if (elem == 26) { // stop codon |
---|
60 | result[0] = '*'; |
---|
61 | result[1] = 0; |
---|
62 | } |
---|
63 | else if (elem == 27) { // gaps |
---|
64 | result[0] = '-'; |
---|
65 | result[1] = '.'; |
---|
66 | } |
---|
67 | |
---|
68 | return result; |
---|
69 | } |
---|
70 | static const char *default_color(int cset, int elem) { |
---|
71 | // returns default color numbers for seq-color-set |
---|
72 | static char result[3] = "=0"; |
---|
73 | const char *pos = default_sets[cset]+2*elem; |
---|
74 | |
---|
75 | result[0] = pos[0]; |
---|
76 | result[1] = pos[1]; |
---|
77 | |
---|
78 | if (result[0] == '=' && result[1] == '0') result[0] = 0; |
---|
79 | |
---|
80 | return result; |
---|
81 | } |
---|
82 | |
---|
83 | static void color_awar_changed_cb(AW_root *, ED4_seq_colors *sc) { |
---|
84 | sc->reload(); |
---|
85 | } |
---|
86 | |
---|
87 | static void create_seq_color_awars(AW_root *awr, ED4_seq_colors *sc) { |
---|
88 | e4_assert(!seq_color_awars_created); |
---|
89 | |
---|
90 | RootCallback update_cb = makeRootCallback(color_awar_changed_cb, sc); |
---|
91 | awr->awar_int(AWAR_SEQ_NAME_SELECTOR_NA, default_NUC_set, AW_ROOT_DEFAULT)->add_callback(update_cb); |
---|
92 | awr->awar_int(AWAR_SEQ_NAME_SELECTOR_AA, default_AMI_set, AW_ROOT_DEFAULT)->add_callback(update_cb); |
---|
93 | |
---|
94 | for (int elem = 0; elem<SEQ_COLOR_SET_ELEMS; ++elem) { |
---|
95 | const char *awar_name = GBS_global_string(AWAR_SEQ_NAME_STRINGS_TEMPLATE, elem); |
---|
96 | awr->awar_string(awar_name, default_characters(elem))->add_callback(update_cb); |
---|
97 | |
---|
98 | for (int cset = 0; cset<SEQ_COLOR_SETS; ++cset) { |
---|
99 | awar_name = GBS_global_string(AWAR_SEQ_NAME_TEMPLATE, cset, elem); |
---|
100 | AW_awar *awar_col = awr->awar_string(awar_name, default_color(cset, elem)); |
---|
101 | |
---|
102 | if (strcmp(awar_col->read_char_pntr(), "=0") == 0) { // translate old->new default |
---|
103 | awar_col->write_string(""); |
---|
104 | } |
---|
105 | |
---|
106 | // add callback AFTER writing to awar above to avoid recursion |
---|
107 | // (the CB calls this function again, and seq_color_awars_created is set |
---|
108 | // to true at the very end... |
---|
109 | awar_col->add_callback(update_cb); |
---|
110 | } |
---|
111 | } |
---|
112 | |
---|
113 | seq_color_awars_created = true; |
---|
114 | } |
---|
115 | |
---|
116 | AW_window *ED4_create_seq_colors_window(AW_root *awr, ED4_seq_colors *sc) { |
---|
117 | char buf[256]; |
---|
118 | static AW_window_simple *aws = 0; |
---|
119 | if (aws) return aws; |
---|
120 | |
---|
121 | if (!seq_color_awars_created) create_seq_color_awars(awr, sc); |
---|
122 | |
---|
123 | aws = new AW_window_simple; |
---|
124 | aws->init(awr, "SEQUENCE_MAPPING", "Sequence color mapping"); |
---|
125 | |
---|
126 | aws->at(10, 10); |
---|
127 | aws->auto_space(0, 3); |
---|
128 | |
---|
129 | aws->callback(AW_POPDOWN); |
---|
130 | aws->create_button("CLOSE", "CLOSE", "C"); |
---|
131 | |
---|
132 | aws->callback(makeHelpCallback("sequence_colors.hlp")); |
---|
133 | aws->create_button("HELP", "HELP"); |
---|
134 | |
---|
135 | aws->at_newline(); |
---|
136 | |
---|
137 | for (int seqType=0; seqType<2; seqType++) { |
---|
138 | if (seqType==0) { |
---|
139 | aws->label("Select color-set for Nucleotides (NA):"); |
---|
140 | aws->create_toggle_field(AWAR_SEQ_NAME_SELECTOR_NA, 1); |
---|
141 | } |
---|
142 | else { |
---|
143 | aws->label("Select color-set for Amino Acids (AA):"); |
---|
144 | aws->create_toggle_field(AWAR_SEQ_NAME_SELECTOR_AA, 1); |
---|
145 | } |
---|
146 | |
---|
147 | for (int cset = 0; cset < SEQ_COLOR_SETS; cset++) { |
---|
148 | sprintf(buf, "%i", cset+1); |
---|
149 | aws->insert_toggle(buf, " ", cset); |
---|
150 | } |
---|
151 | aws->update_toggle_field(); |
---|
152 | aws->at_newline(); |
---|
153 | } |
---|
154 | |
---|
155 | const int BIG_COLUMNS = 2; |
---|
156 | const int CHAR_COL_WIDTH = 4; |
---|
157 | const int SET_COL_WIDTH = 2; |
---|
158 | |
---|
159 | int col_x_off[BIG_COLUMNS][SEQ_COLOR_SETS+1]; |
---|
160 | |
---|
161 | aws->auto_space(3, 2); |
---|
162 | |
---|
163 | for (int bcol = 0; bcol<BIG_COLUMNS; ++bcol) { |
---|
164 | col_x_off[bcol][0] = aws->get_at_xposition(); |
---|
165 | aws->button_length(CHAR_COL_WIDTH); |
---|
166 | aws->create_button(0, "Chars"); |
---|
167 | |
---|
168 | aws->button_length(SET_COL_WIDTH); |
---|
169 | for (int cset = 0; cset < SEQ_COLOR_SETS; cset++) { |
---|
170 | sprintf(buf, " %i", cset+1); |
---|
171 | col_x_off[bcol][cset+1] = aws->get_at_xposition(); |
---|
172 | aws->create_button(0, buf); |
---|
173 | } |
---|
174 | |
---|
175 | if (!bcol) { |
---|
176 | int set_col_pixel_width = col_x_off[0][1]-col_x_off[0][0]; |
---|
177 | aws->at_x(aws->get_at_xposition()+set_col_pixel_width); |
---|
178 | } |
---|
179 | } |
---|
180 | |
---|
181 | aws->at_newline(); |
---|
182 | |
---|
183 | const int ROWS = SEQ_COLOR_SET_ELEMS/2; |
---|
184 | for (int r = 0; r<ROWS; r++) { |
---|
185 | for (int bcol = 0; bcol<BIG_COLUMNS; ++bcol) { |
---|
186 | int elem = bcol*ROWS+r; |
---|
187 | |
---|
188 | sprintf(buf, AWAR_SEQ_NAME_STRINGS_TEMPLATE, elem); |
---|
189 | aws->at_x(col_x_off[bcol][0]); |
---|
190 | aws->create_input_field(buf, CHAR_COL_WIDTH); |
---|
191 | |
---|
192 | for (int cset = 0; cset < SEQ_COLOR_SETS; cset++) { |
---|
193 | sprintf(buf, AWAR_SEQ_NAME_TEMPLATE, cset, elem); |
---|
194 | aws->at_x(col_x_off[bcol][cset+1]); |
---|
195 | aws->create_input_field(buf, SET_COL_WIDTH); |
---|
196 | } |
---|
197 | } |
---|
198 | aws->at_newline(); |
---|
199 | } |
---|
200 | |
---|
201 | aws->window_fit(); |
---|
202 | |
---|
203 | return aws; |
---|
204 | } |
---|
205 | |
---|
206 | void ED4_seq_colors::reload() { |
---|
207 | for (int i=0; i<256; i++) { |
---|
208 | char_2_gc[i] = char_2_gc_aa[i] = base_gc; |
---|
209 | char_2_char[i] = char_2_char_aa[i] = i; |
---|
210 | } |
---|
211 | |
---|
212 | AW_root *aw_root = AW_root::SINGLETON; |
---|
213 | |
---|
214 | if (!seq_color_awars_created) create_seq_color_awars(aw_root, this); |
---|
215 | |
---|
216 | const char *selector_awar[2] = { AWAR_SEQ_NAME_SELECTOR_NA, AWAR_SEQ_NAME_SELECTOR_AA }; |
---|
217 | |
---|
218 | for (int selector = 0; selector<2; selector++) { |
---|
219 | long def_set = selector == 0 ? default_NUC_set : default_AMI_set; |
---|
220 | long cset = aw_root->awar(selector_awar[selector])->read_int(); |
---|
221 | |
---|
222 | if (cset < 0 || cset >= SEQ_COLOR_SETS) { |
---|
223 | cset = def_set; |
---|
224 | } |
---|
225 | |
---|
226 | for (int elem = 0; elem < SEQ_COLOR_SET_ELEMS; elem++) { |
---|
227 | char awar_name[256]; |
---|
228 | |
---|
229 | sprintf(awar_name, AWAR_SEQ_NAME_STRINGS_TEMPLATE, elem); |
---|
230 | unsigned char *sc = (unsigned char *)aw_root->awar(awar_name)->read_string(); |
---|
231 | |
---|
232 | sprintf(awar_name, AWAR_SEQ_NAME_TEMPLATE, (int)cset, elem); |
---|
233 | char *val = aw_root->awar(awar_name)->read_string(); |
---|
234 | if (!val[0]) freedup(val, "=0"); // interpret '' as ' = 0' |
---|
235 | |
---|
236 | if (strlen(val) != 2 || val[1] >'9' || val[1] < '0') { |
---|
237 | aw_message(GB_export_errorf("Error in Color Lookup Table: '%s' is not of type X#", val)); |
---|
238 | } |
---|
239 | else { |
---|
240 | if (selector == 0) { // Nucleotide colors |
---|
241 | for (int i=0; sc[i]; i++) { |
---|
242 | char_2_gc[sc[i]] = val[1]-'0' + base_gc; |
---|
243 | if (val[0] != '=') char_2_char[sc[i]] = val[0]; |
---|
244 | } |
---|
245 | } |
---|
246 | else { |
---|
247 | for (int i=0; sc[i]; i++) { |
---|
248 | char_2_gc_aa[sc[i]] = val[1]-'0' + base_gc; |
---|
249 | if (val[0] != '=') char_2_char_aa[sc[i]] = val[0]; |
---|
250 | } |
---|
251 | } |
---|
252 | } |
---|
253 | free(val); |
---|
254 | free(sc); |
---|
255 | } |
---|
256 | } |
---|
257 | |
---|
258 | run_cb(); |
---|
259 | } |
---|
260 | |
---|
261 | ED4_seq_colors::ED4_seq_colors(int baseGC, void (*changed_cb)()) { |
---|
262 | cb = changed_cb; |
---|
263 | base_gc = baseGC; |
---|
264 | |
---|
265 | this->reload(); |
---|
266 | } |
---|
267 | |
---|
268 | // ----------------------- |
---|
269 | // ED4_reference |
---|
270 | |
---|
271 | ED4_reference::ED4_reference(GBDATA *_gb_main) |
---|
272 | : gb_main(_gb_main), |
---|
273 | nodiff('#'), // notused; overwritten by user default later |
---|
274 | mindcase(true), |
---|
275 | ref_len(0), |
---|
276 | reference(NULL), |
---|
277 | ref_term(NULL) |
---|
278 | { |
---|
279 | reset_gap_table(); |
---|
280 | } |
---|
281 | |
---|
282 | ED4_reference::~ED4_reference() { |
---|
283 | clear(); |
---|
284 | } |
---|
285 | |
---|
286 | void ED4_reference::reset_gap_table() { |
---|
287 | for (int i = 0; i<256; ++i) is_gap[i] = false; |
---|
288 | } |
---|
289 | |
---|
290 | void ED4_reference::set_gap_handling(bool mindgaptype, const char *gaptypes) { |
---|
291 | reset_gap_table(); |
---|
292 | if (!mindgaptype) { // treat all gaps as "equal" |
---|
293 | for (int i = 0; gaptypes[i]; ++i) { |
---|
294 | is_gap[safeCharIndex(gaptypes[i])] = true; |
---|
295 | } |
---|
296 | } |
---|
297 | } |
---|
298 | |
---|
299 | void ED4_reference::expand_to_length(int len) { |
---|
300 | if (len>ref_len && is_set()) { |
---|
301 | char *ref2 = (char *)GB_calloc(sizeof(char), len+1); |
---|
302 | |
---|
303 | if (reference) { |
---|
304 | strcpy(ref2, reference); |
---|
305 | free(reference); |
---|
306 | } |
---|
307 | reference = ref2; |
---|
308 | ref_len = len; |
---|
309 | } |
---|
310 | } |
---|
311 | |
---|
312 | void ED4_reference::update_data() { |
---|
313 | freeset(reference, ref_term->get_sequence_copy(&ref_len)); |
---|
314 | } |
---|
315 | |
---|
316 | void ED4_reference::data_changed_cb(ED4_species_manager *IF_ASSERTION_USED(calledFrom)) { |
---|
317 | e4_assert(ref_term); |
---|
318 | if (ref_term) { |
---|
319 | #if defined(ASSERTION_USED) |
---|
320 | if (calledFrom) e4_assert(ref_term->get_parent(ED4_L_SPECIES)->to_species_manager() == calledFrom); |
---|
321 | #endif |
---|
322 | update_data(); |
---|
323 | } |
---|
324 | } |
---|
325 | static void refdata_changed_cb(ED4_species_manager *sman, ED4_reference *ref) { |
---|
326 | ref->data_changed_cb(sman); |
---|
327 | ED4_ROOT->request_refresh_for_specific_terminals(ED4_L_SEQUENCE_STRING); // refresh all sequences |
---|
328 | } |
---|
329 | static void refdata_deleted_cb() { |
---|
330 | ED4_viewDifferences_disable(); |
---|
331 | } |
---|
332 | |
---|
333 | void ED4_reference::clear() { |
---|
334 | // remove change cb |
---|
335 | if (ref_term) { |
---|
336 | ED4_species_manager *sman = ref_term->get_parent(ED4_L_SPECIES)->to_species_manager(); |
---|
337 | sman->remove_sequence_changed_cb(makeED4_species_managerCallback(refdata_changed_cb, this)); |
---|
338 | sman->remove_delete_callback(makeED4_managerCallback(refdata_deleted_cb)); |
---|
339 | } |
---|
340 | |
---|
341 | freenull(reference); |
---|
342 | ref_len = 0; |
---|
343 | ref_term = NULL; |
---|
344 | } |
---|
345 | |
---|
346 | void ED4_reference::define(const ED4_sequence_terminal *rterm) { |
---|
347 | clear(); |
---|
348 | ref_term = rterm; |
---|
349 | update_data(); |
---|
350 | |
---|
351 | // add change cb |
---|
352 | ED4_species_manager *sman = ref_term->get_parent(ED4_L_SPECIES)->to_species_manager(); |
---|
353 | sman->add_sequence_changed_cb(makeED4_species_managerCallback(refdata_changed_cb, this)); |
---|
354 | sman->add_delete_callback(makeED4_managerCallback(refdata_deleted_cb)); |
---|
355 | } |
---|
356 | |
---|
357 | bool ED4_reference::reference_is_a_consensus() const { |
---|
358 | return is_set() && ref_term->is_consensus_sequence_terminal(); |
---|
359 | } |
---|
360 | |
---|
361 | // -------------------------------------------------------------------------------- |
---|
362 | |
---|
363 | #define APREFIX_DIFF_SAVE "edit4/diff/" |
---|
364 | #define APREFIX_DIFF_TEMP "tmp/" APREFIX_DIFF_SAVE |
---|
365 | |
---|
366 | #define AWAR_DIFF_TYPE APREFIX_DIFF_TEMP "type" |
---|
367 | #define AWAR_DIFF_NAME APREFIX_DIFF_TEMP "name" |
---|
368 | #define AWAR_NODIFF_INDICATOR APREFIX_DIFF_SAVE "indicator" |
---|
369 | #define AWAR_DIFF_MINDCASE APREFIX_DIFF_SAVE "mindcase" |
---|
370 | #define AWAR_DIFF_MINDGAPTYPE APREFIX_DIFF_SAVE "mindgaptype" |
---|
371 | #define AWAR_DIFF_GAPTYPES APREFIX_DIFF_SAVE "gaptypes" |
---|
372 | |
---|
373 | enum ViewDiffType { |
---|
374 | VD_DISABLED, |
---|
375 | VD_SELECTED, |
---|
376 | VD_FOLLOW, |
---|
377 | }; |
---|
378 | |
---|
379 | static ED4_terminal *detect_current_ref_terminal() { |
---|
380 | ED4_cursor *cursor = ¤t_cursor(); |
---|
381 | ED4_terminal *refTerm = cursor->owner_of_cursor; |
---|
382 | |
---|
383 | if (refTerm) { |
---|
384 | if (!(refTerm->is_consensus_terminal() || |
---|
385 | refTerm->is_SAI_terminal() || |
---|
386 | refTerm->is_species_seq_terminal())) |
---|
387 | { |
---|
388 | refTerm = NULL; |
---|
389 | } |
---|
390 | } |
---|
391 | |
---|
392 | if (!refTerm) { |
---|
393 | aw_message("Please set the cursor to a species, SAI or group consensus."); |
---|
394 | } |
---|
395 | |
---|
396 | return refTerm; |
---|
397 | } |
---|
398 | |
---|
399 | static void set_diff_reference(ED4_terminal *refTerm) { |
---|
400 | ED4_reference *ref = ED4_ROOT->reference; |
---|
401 | if (!refTerm) { |
---|
402 | ref->clear(); |
---|
403 | } |
---|
404 | else { |
---|
405 | ED4_sequence_terminal *refSeqTerm = dynamic_cast<ED4_sequence_terminal*>(refTerm); |
---|
406 | if (refSeqTerm) { |
---|
407 | AW_awar *awar_refName = AW_root::SINGLETON->awar(AWAR_DIFF_NAME); |
---|
408 | ED4_species_name_terminal *nameTerm = refSeqTerm->corresponding_species_name_terminal(); |
---|
409 | |
---|
410 | ref->define(refSeqTerm); |
---|
411 | if (refTerm->is_consensus_terminal()) { |
---|
412 | awar_refName->write_string(GBS_global_string("consensus %s", nameTerm->get_displayed_text())); |
---|
413 | } |
---|
414 | else { |
---|
415 | e4_assert(refTerm->is_species_seq_terminal() || refTerm->is_SAI_terminal()); |
---|
416 | awar_refName->write_string(nameTerm->get_displayed_text()); |
---|
417 | } |
---|
418 | } |
---|
419 | else { |
---|
420 | aw_message("Not supported for this terminal type"); |
---|
421 | } |
---|
422 | } |
---|
423 | |
---|
424 | ED4_ROOT->request_refresh_for_specific_terminals(ED4_L_SEQUENCE_STRING); |
---|
425 | } |
---|
426 | |
---|
427 | static SmartCharPtr last_used_ref_term_name; |
---|
428 | |
---|
429 | static void set_current_as_diffRef(bool enable) { |
---|
430 | ED4_MostRecentWinContext context; |
---|
431 | |
---|
432 | ED4_terminal *refTerm = enable ? detect_current_ref_terminal() : NULL; |
---|
433 | if (!enable || refTerm) { // do not disable, if current terminal has wrong type |
---|
434 | set_diff_reference(refTerm); |
---|
435 | if (refTerm) last_used_ref_term_name = strdup(refTerm->id); |
---|
436 | } |
---|
437 | } |
---|
438 | |
---|
439 | static void change_reference_cb(AW_window *aww) { |
---|
440 | set_current_as_diffRef(true); |
---|
441 | |
---|
442 | AW_awar *awar_refType = aww->get_root()->awar(AWAR_DIFF_TYPE); |
---|
443 | if (awar_refType->read_int() == VD_DISABLED) { |
---|
444 | awar_refType->write_int(VD_SELECTED); |
---|
445 | } |
---|
446 | } |
---|
447 | |
---|
448 | static void diff_type_changed_cb(AW_root *awr) { |
---|
449 | AW_awar *awar_refType = awr->awar(AWAR_DIFF_TYPE); |
---|
450 | ViewDiffType type = ViewDiffType(awar_refType->read_int()); |
---|
451 | |
---|
452 | switch (type) { |
---|
453 | case VD_DISABLED: |
---|
454 | set_current_as_diffRef(false); |
---|
455 | break; |
---|
456 | |
---|
457 | case VD_FOLLOW: |
---|
458 | case VD_SELECTED: { |
---|
459 | ED4_terminal *last_used_ref_term = NULL; |
---|
460 | if (last_used_ref_term_name.isSet()) { |
---|
461 | ED4_base *found = ED4_ROOT->main_manager->search_ID(&*last_used_ref_term_name); |
---|
462 | if (found && found->is_terminal()) { |
---|
463 | last_used_ref_term = found->to_terminal(); |
---|
464 | } |
---|
465 | } |
---|
466 | if (last_used_ref_term) { |
---|
467 | set_diff_reference(last_used_ref_term); |
---|
468 | if (type == VD_FOLLOW) set_current_as_diffRef(true); |
---|
469 | } |
---|
470 | else { |
---|
471 | set_current_as_diffRef(true); |
---|
472 | } |
---|
473 | if (!ED4_ROOT->reference->is_set()) { |
---|
474 | awar_refType->write_int(VD_DISABLED); |
---|
475 | } |
---|
476 | break; |
---|
477 | } |
---|
478 | } |
---|
479 | } |
---|
480 | |
---|
481 | static void update_reference_settings(AW_root *awr) { |
---|
482 | ED4_reference *ref = ED4_ROOT->reference; |
---|
483 | ref->set_nodiff_indicator(awr->awar(AWAR_NODIFF_INDICATOR)->read_char_pntr()[0]); |
---|
484 | ref->set_case_sensitive(awr->awar(AWAR_DIFF_MINDCASE)->read_int()); |
---|
485 | ref->set_gap_handling(awr->awar(AWAR_DIFF_MINDGAPTYPE)->read_int(), awr->awar(AWAR_DIFF_GAPTYPES)->read_char_pntr()); |
---|
486 | } |
---|
487 | static void diff_setting_changed_cb(AW_root *awr) { |
---|
488 | update_reference_settings(awr); |
---|
489 | ED4_ROOT->request_refresh_for_specific_terminals(ED4_L_SEQUENCE_STRING); |
---|
490 | } |
---|
491 | |
---|
492 | static void nodiff_indicator_changed_cb(AW_root *awr) { |
---|
493 | AW_awar *awar_indicator = awr->awar(AWAR_NODIFF_INDICATOR); |
---|
494 | const char *indicator = awar_indicator->read_char_pntr(); |
---|
495 | |
---|
496 | if (!indicator[0]) { |
---|
497 | awar_indicator->write_string(" "); |
---|
498 | } |
---|
499 | else { |
---|
500 | diff_setting_changed_cb(awr); |
---|
501 | } |
---|
502 | } |
---|
503 | |
---|
504 | static bool viewDifferences_awars_initialized = false; |
---|
505 | |
---|
506 | static void create_viewDifferences_awars(AW_root *awr) { |
---|
507 | if (!viewDifferences_awars_initialized) { |
---|
508 | awr->awar_int(AWAR_DIFF_TYPE, VD_DISABLED)->add_callback(diff_type_changed_cb); |
---|
509 | awr->awar_string(AWAR_DIFF_NAME, "<none selected>"); |
---|
510 | awr->awar_string(AWAR_NODIFF_INDICATOR, " ")->add_callback(nodiff_indicator_changed_cb)->set_srt(" ?=?:? =?:?*=?"); |
---|
511 | awr->awar_int(AWAR_DIFF_MINDCASE, 1)->add_callback(diff_setting_changed_cb); |
---|
512 | awr->awar_int(AWAR_DIFF_MINDGAPTYPE, 1)->add_callback(diff_setting_changed_cb); |
---|
513 | awr->awar_string(AWAR_DIFF_GAPTYPES, "-=.?")->add_callback(diff_setting_changed_cb); |
---|
514 | |
---|
515 | viewDifferences_awars_initialized = true; |
---|
516 | } |
---|
517 | } |
---|
518 | |
---|
519 | void ED4_toggle_viewDifferences(AW_root *awr) { |
---|
520 | static ViewDiffType lastActiveType = VD_SELECTED; |
---|
521 | |
---|
522 | create_viewDifferences_awars(awr); |
---|
523 | update_reference_settings(awr); |
---|
524 | |
---|
525 | AW_awar *awar_difftype = awr->awar(AWAR_DIFF_TYPE); |
---|
526 | ViewDiffType currType = ViewDiffType(awar_difftype->read_int()); |
---|
527 | |
---|
528 | if (currType == VD_DISABLED || !ED4_ROOT->reference->is_set()) { |
---|
529 | currType = lastActiveType; |
---|
530 | } |
---|
531 | else { |
---|
532 | lastActiveType = currType; |
---|
533 | currType = VD_DISABLED; |
---|
534 | } |
---|
535 | |
---|
536 | awar_difftype->rewrite_int(currType); // rewrite to allow activation after automatic deactivation in ED4_reference (e.g. by killing ref-term) |
---|
537 | } |
---|
538 | void ED4_viewDifferences_setNewReference() { |
---|
539 | set_current_as_diffRef(true); |
---|
540 | } |
---|
541 | void ED4_viewDifferences_announceTerminalChange() { |
---|
542 | if (ED4_ROOT->reference->is_set() && |
---|
543 | ED4_ROOT->aw_root->awar(AWAR_DIFF_TYPE)->read_int() == VD_FOLLOW) |
---|
544 | { |
---|
545 | ED4_viewDifferences_setNewReference(); |
---|
546 | } |
---|
547 | } |
---|
548 | void ED4_viewDifferences_disable() { |
---|
549 | set_current_as_diffRef(false); |
---|
550 | } |
---|
551 | |
---|
552 | AW_window *ED4_create_viewDifferences_window(AW_root *awr) { |
---|
553 | static AW_window_simple *aws = 0; |
---|
554 | if (!aws) { |
---|
555 | if (!ED4_ROOT->reference->is_set()) ED4_toggle_viewDifferences(awr); // automatically activate if off |
---|
556 | |
---|
557 | aws = new AW_window_simple; |
---|
558 | aws->init(awr, "VIEW_DIFF", "View sequence differences"); |
---|
559 | aws->load_xfig("edit4/viewdiff.fig"); |
---|
560 | |
---|
561 | aws->at("close"); |
---|
562 | aws->callback(AW_POPDOWN); |
---|
563 | aws->create_button("CLOSE", "CLOSE", "C"); |
---|
564 | |
---|
565 | aws->at("help"); |
---|
566 | aws->callback(makeHelpCallback("viewdiff.hlp")); |
---|
567 | aws->create_button("HELP", "HELP"); |
---|
568 | |
---|
569 | aws->at("show"); |
---|
570 | aws->create_toggle_field(AWAR_DIFF_TYPE); |
---|
571 | aws->insert_toggle("None (=disable)", "N", VD_DISABLED); |
---|
572 | aws->insert_toggle("Selected:", "S", VD_SELECTED); |
---|
573 | aws->insert_toggle("Follow cursor", "F", VD_FOLLOW); |
---|
574 | aws->update_toggle_field(); |
---|
575 | |
---|
576 | aws->at("ref"); |
---|
577 | aws->button_length(20); |
---|
578 | aws->create_button(NULL, AWAR_DIFF_NAME, NULL, "+"); |
---|
579 | |
---|
580 | aws->at("set"); |
---|
581 | aws->button_length(4); |
---|
582 | aws->callback(change_reference_cb); |
---|
583 | aws->create_button("SET", "SET"); |
---|
584 | |
---|
585 | aws->at("nodiff"); |
---|
586 | aws->create_input_field(AWAR_NODIFF_INDICATOR); |
---|
587 | |
---|
588 | aws->at("case"); |
---|
589 | aws->create_toggle(AWAR_DIFF_MINDCASE); |
---|
590 | |
---|
591 | aws->at("gap"); |
---|
592 | aws->create_toggle(AWAR_DIFF_MINDGAPTYPE); |
---|
593 | aws->at("gapchars"); |
---|
594 | aws->create_input_field(AWAR_DIFF_GAPTYPES, 8); |
---|
595 | } |
---|
596 | return aws; |
---|
597 | } |
---|