NetSurf
button_bar.c
Go to the documentation of this file.
1/*
2 * Copyright 2004, 2005 Richard Wilson <info@tinct.net>
3 * Copyright 2011 Stephen Fryatt <stevef@netsurf-browser.org>
4 *
5 * This file is part of NetSurf, http://www.netsurf-browser.org/
6 *
7 * NetSurf is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * NetSurf is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20/** \file
21 * Button bars (implementation).
22 */
23
24#include <assert.h>
25#include <stdio.h>
26#include <stdbool.h>
27#include <stdlib.h>
28#include <string.h>
29#include <oslib/dragasprite.h>
30#include <oslib/os.h>
31#include <oslib/osspriteop.h>
32#include <oslib/wimp.h>
33#include <oslib/wimpspriteop.h>
34
35#include "utils/log.h"
36
38#include "riscos/gui.h"
39#include "riscos/mouse.h"
40#include "riscos/theme.h"
41#include "riscos/wimp.h"
42
43#define BUTTONBAR_SPRITE_NAME_LENGTH 12
44#define BUTTONBAR_VALIDATION_LENGTH 40
45
47 wimp_i icon;
48 bool shaded;
50
53
56
59 char opt_key;
60 const char *help_suffix;
61
64};
65
66
67struct button_bar {
68 /** The applied theme (or NULL to use the default) */
70
71 /** The widget dimensions. */
75
77
78 /** The window details and bar position. */
79 wimp_w window;
80 os_box extent;
81 osspriteop_area *sprites;
83
84 bool hidden;
85
86 bool edit;
89 void (*edit_refresh)(void *);
91
92 /** The list of all the defined buttons. */
93
95
96 /** The list of the buttons in the current bar. */
97
99};
100
101static char null_text_string[] = "";
102static char separator_name[] = "separator";
103
104static struct button_bar *drag_start = NULL;
105static char drag_opt = '\0';
106static bool drag_separator = false;
107
108/*
109 * Private function prototypes.
110 */
111
115static void ro_gui_button_bar_drag_end(wimp_dragged *drag, void *data);
116static void ro_gui_button_bar_sync_editors(struct button_bar *target,
117 struct button_bar *source);
119 struct button_bar *button_bar, wimp_i icon);
121 struct button_bar *button_bar, char opt_key);
123 struct button_bar *button_bar, button_bar_action action);
125 struct button_bar *button_bar, os_coord pos,
126 bool *separator, bool *right);
127
128/* This is an exported interface documented in button_bar.h */
129
131 const struct button_bar_buttons buttons[])
132{
133 struct button_bar *button_bar;
134 struct button_bar_button *icon, *new_icon;
135 int def;
136
137 /* Allocate memory. */
138
139 button_bar = malloc(sizeof(struct button_bar));
140 if (button_bar == NULL) {
141 NSLOG(netsurf, INFO, "No memory for malloc()");
142 return NULL;
143 }
144
145 /* Set up default parameters. */
146
149 button_bar->background = wimp_COLOUR_VERY_LIGHT_GREY;
150
151 button_bar->x_min = -1;
152 button_bar->y_min = -1;
155
156 button_bar->separators = false;
157
158 button_bar->window = NULL;
159
160 button_bar->hidden = false;
161
162 button_bar->edit = false;
163 button_bar->edit_target = NULL;
164 button_bar->edit_source = NULL;
165 button_bar->edit_refresh = NULL;
167
168 button_bar->buttons = NULL;
169
170 /* Process the button icon definitions */
171
172 icon = NULL;
173
174 for (def = 0; buttons[def].icon != NULL; def++) {
175 new_icon = malloc(sizeof(struct button_bar_button));
176 if (new_icon == NULL) {
177 break;
178 }
179
180 if (icon == NULL) {
181 button_bar->buttons = new_icon;
182 button_bar->bar = new_icon;
183 } else {
184 icon->next = new_icon;
185 icon->bar_next = new_icon;
186 }
187 icon = new_icon;
188 icon->next = NULL;
189 icon->bar_next = NULL;
190
191 strncpy(icon->sprite, buttons[def].icon,
193 icon->sprite[BUTTONBAR_SPRITE_NAME_LENGTH-1] = 0;
194 snprintf(icon->validation, BUTTONBAR_VALIDATION_LENGTH,
195 "R5;S%s,p%s", icon->sprite, icon->sprite);
196
197 icon->icon = -1;
198 icon->shaded = false;
199 icon->separator = false;
200
201 icon->select_action = buttons[def].select;
202 icon->adjust_action = buttons[def].adjust;
203 icon->opt_key = buttons[def].opt_key;
204 icon->help_suffix = buttons[def].help;
205 }
206
207 /* Add a separator after the last entry. This will be lost if the
208 * buttons are subsequently set, but is used for the edit source bar.
209 */
210
211 if (icon != NULL)
212 icon->separator = true;
213
214 return button_bar;
215}
216
217
218/* This is an exported interface documented in button_bar.h */
219
221 struct button_bar *source, void (* refresh)(void *),
222 void *client_data)
223{
224 if (target == NULL || source == NULL ||
225 target->edit_target != NULL ||
226 target->edit_source != NULL ||
227 source->edit_target != NULL ||
228 source->edit_source != NULL)
229 return false;
230
231 target->edit_source = source;
232 source->edit_target = target;
233
234 /* Store the callback data in the editor bar. */
235
236 source->edit_refresh = refresh;
237 source->edit_client_data = client_data;
238
239 return true;
240}
241
242
243/* This is an exported interface documented in button_bar.h */
244
246 struct theme_descriptor *theme, theme_style style,
247 wimp_w window, bool edit)
248{
249 struct button_bar_button *button;
250 int height;
251
252
253 if (button_bar == NULL)
254 return false;
255
257 button_bar->window = window;
261
262 button_bar->edit = edit;
263
264 height = 0;
268
269 /* If the separator height is 0, then either the sprite really is
270 * zero pixels high or the default was used as no sprite was found.
271 * Either way, we don't have a separator.
272 */
273
274 button_bar->separators = (height == 0) ? false : true;
275
276 button = button_bar->buttons;
277
278 while (button != NULL) {
279 button->x_size = 0;
280 button->y_size = 0;
281 button->icon = -1;
282
284 button->sprite,
285 &button->x_size, &button->y_size);
286
287 button = button->next;
288 }
289
291 return false;
292
293 if (button_bar->edit && button_bar->edit_target != NULL)
295 button_bar);
296
298}
299
300
301/* This is an exported interface documented in button_bar.h */
302
304 char order[])
305{
306 struct button_bar_button *button, *new;
307 int i;
308
309 if (button_bar == NULL || order == NULL)
310 return false;
311
312 /* Delete any existing button arrangement. */
313
314 button_bar->bar = NULL;
315
316 for (button = button_bar->buttons; button != NULL;
317 button = button->next) {
318 button->bar_next = NULL;
319 button->separator = false;
320 }
321
322 /* Parse the config string and link up the new buttons. */
323
324 button = NULL;
325
326 for (i = 0; order[i] != '\0'; i++) {
327 if (order[i] != '|') {
329 order[i]);
330
331 if (new != NULL) {
332 if (button == NULL)
333 button_bar->bar = new;
334 else
335 button->bar_next = new;
336
337 button = new;
338 }
339 } else {
340 if (button != NULL)
341 button->separator = true;
342 }
343 }
344
346 return false;
347
349}
350
351/**
352 * Place the buttons on a button bar, taking into account the button arrangement
353 * and the current theme, and update the bar extent details.
354 *
355 * \param *button_bar The button bar to update.
356 * \return true if successful; else false.
357 */
358
360{
361 struct button_bar_button *button;
362 int x_pos, y_pos, height;
363
364 if (button_bar == NULL)
365 return false;
366
367 button = button_bar->bar;
368 x_pos = 0;
369 y_pos = 0;
370 height = 0;
371
372 while (button != NULL) {
373 button->x_pos = x_pos;
374 button->y_pos = y_pos;
375
376 x_pos += button->x_size;
377 if (button->separator)
379
380 if (button->y_size > height)
381 height = button->y_size;
382
383 button = button->bar_next;
384 }
385
388
389 return true;
390}
391
392
393/* This is an exported interface documented in button_bar.h */
394
396{
397 struct button_bar_button *button;
398
399 if (button_bar == NULL)
400 return;
401
402 /* Free the button definitions. */
403
404 while (button_bar->buttons != NULL) {
405 button = button_bar->buttons;
406 button_bar->buttons = button->next;
407 free(button);
408 }
409
410 free(button_bar);
411}
412
413
414/* This is an exported interface documented in button_bar.h */
415
417 int *width, int *height)
418{
419 if (button_bar == NULL)
420 return false;
421
422 if (button_bar->x_min != -1 && button_bar->y_min != -1) {
423 if (width != NULL)
425 if (height != NULL)
427
428 return true;
429 }
430
431 return false;
432}
433
434
435/* This is an exported interface documented in button_bar.h */
436
438 int x0, int y0, int x1, int y1)
439{
440 if (button_bar == NULL)
441 return false;
442
443 if ((x1 - x0) < button_bar->x_min || (y1 - y0) < button_bar->y_min)
444 return false;
445
446 if (button_bar->extent.x0 == x0 && button_bar->extent.y0 == y0 &&
447 button_bar->extent.x1 == x1 &&
448 button_bar->extent.y1 == y1)
449 return true;
450
451 /* Redraw the relevant bits of the toolbar. We can't optimise for
452 * stretching the X-extent, as this probably means the button
453 * arrangement has changed which necessitates a full redraw anyway.
454 */
455
456 if (button_bar->window != NULL) {
457 xwimp_force_redraw(button_bar->window,
460 xwimp_force_redraw(button_bar->window, x0, y0, x1, y1);
461 }
462
463 button_bar->extent.x0 = x0;
464 button_bar->extent.y0 = y0;
465 button_bar->extent.x1 = x1;
466 button_bar->extent.y1 = y1;
467
468 if ((y1 - y0) > button_bar->y_min)
470 ((y1 - y0) - button_bar->y_min) / 2;
471 else
473
475}
476
477
478/**
479 * Update the icons on a button bar, creating or deleting them from the window
480 * as necessary.
481 */
482
484{
485 wimp_icon_create icon;
486 struct button_bar_button *button, *b;
487 os_error *error;
488
489
490 if (button_bar == NULL || button_bar->window == NULL)
491 return (button_bar == NULL) ? false : true;
492
493 button = button_bar->buttons;
494
495 while (button != NULL) {
496 bool on_bar = false;
497
498 /* Check if the icon is currently on the bar. */
499
500 for (b = button_bar->bar; b != NULL; b = b->bar_next) {
501 if (b == button) {
502 on_bar = true;
503 break;
504 }
505 }
506
507 if (on_bar && !button_bar->hidden && button->icon == -1) {
509 icon.icon.extent.x0 = 0;
510 icon.icon.extent.y0 = 0;
511 icon.icon.extent.x1 = 0;
512 icon.icon.extent.y1 = 0;
513 icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_SPRITE |
514 wimp_ICON_INDIRECTED |
515 wimp_ICON_HCENTRED |
516 wimp_ICON_VCENTRED |
518 << wimp_ICON_BG_COLOUR_SHIFT);
519 icon.icon.data.indirected_text.size = 1;
520
521 /* We don't actually shade buttons unless there's no
522 * editor active or this is the source bar.
523 */
524
525 if (button->shaded && (!button_bar->edit ||
526 button_bar->edit_target != NULL))
527 icon.icon.flags |= wimp_ICON_SHADED;
528
529 if (button_bar->edit)
530 icon.icon.flags |= (wimp_BUTTON_CLICK_DRAG <<
531 wimp_ICON_BUTTON_TYPE_SHIFT);
532 else
533 icon.icon.flags |= (wimp_BUTTON_CLICK <<
534 wimp_ICON_BUTTON_TYPE_SHIFT);
535
536 icon.icon.data.indirected_text.text = null_text_string;
537 icon.icon.data.indirected_text.validation =
538 button->validation;
539
540 error = xwimp_create_icon(&icon, &button->icon);
541 if (error) {
542 NSLOG(netsurf, INFO,
543 "xwimp_create_icon: 0x%x: %s",
544 error->errnum,
545 error->errmess);
546 ro_warn_user("WimpError", error->errmess);
547 button->icon = -1;
548 return false;
549 }
550 } else if ((!on_bar || button_bar->hidden)
551 && button->icon != -1) {
552 error = xwimp_delete_icon(button_bar->window,
553 button->icon);
554 if (error != NULL) {
555 NSLOG(netsurf, INFO,
556 "xwimp_delete_icon: 0x%x: %s",
557 error->errnum,
558 error->errmess);
559 ro_warn_user("WimpError", error->errmess);
560 return false;
561 }
562
563 button->icon = -1;
564 }
565
566 button = button->next;
567 }
568
570}
571
572
573/**
574 * Position the icons in the button bar to take account of the currently
575 * configured extent.
576 *
577 * \param *button_bar The button bar to update.
578 * \return true if successful; else false.
579 */
580
582{
583 os_error *error;
584 struct button_bar_button *button;
585
586 if (button_bar == NULL || button_bar->hidden)
587 return (button_bar == NULL) ? false : true;
588
589 /* Reposition all the icons. */
590
591 button = button_bar->bar;
592
593 while (button != NULL) {
594 if(button->icon != -1) {
595 error = xwimp_resize_icon(button_bar->window,
596 button->icon,
597 button_bar->extent.x0 + button->x_pos,
598 button_bar->extent.y0 +
600 button->y_pos,
601 button_bar->extent.x0 + button->x_pos +
602 button->x_size,
603 button_bar->extent.y0 +
605 button->y_pos +
606 button->y_size);
607 if (error != NULL) {
608 NSLOG(netsurf, INFO,
609 "xwimp_resize_icon: 0x%x: %s",
610 error->errnum,
611 error->errmess);
612 ro_warn_user("WimpError", error->errmess);
613 button->icon = -1;
614 return false;
615 }
616 }
617
618 button = button->bar_next;
619 }
620
621 return true;
622}
623
624
625/* This is an exported interface documented in button_bar.h */
626
628{
629 if (button_bar == NULL || button_bar->hidden == hide)
630 return (button_bar == NULL) ? false : true;
631
632 button_bar->hidden = hide;
633
635}
636
637
638/* This is an exported interface documented in button_bar.h */
639
641 button_bar_action action, bool shaded)
642{
643 struct button_bar_button *button;
644
645 if (button_bar == NULL)
646 return false;
647
649 if (button == NULL)
650 return false;
651
652 if (button->shaded == shaded)
653 return true;
654
655 button->shaded = shaded;
656
657 /* We don't actually shade buttons unless there's no editor active
658 * or this is the source bar.
659 */
660
661 if (button->icon != -1 &&
662 (!button_bar->edit || button_bar->edit_target != NULL))
664 shaded);
665
666 return true;
667}
668
669
670/* This is an exported interface documented in button_bar.h */
671
673 wimp_draw *redraw)
674{
675 wimp_icon icon;
676 struct button_bar_button *button;
677
678 /* Test for a valid button bar, and then check that the redraw box
679 * coincides with the bar's extent.
680 */
681
682 if (button_bar == NULL || button_bar->hidden ||
683 (redraw->clip.x0 - (redraw->box.x0 - redraw->xscroll))
684 > button_bar->extent.x1 ||
685 (redraw->clip.y0 - (redraw->box.y1 - redraw->yscroll))
686 > button_bar->extent.y1 ||
687 (redraw->clip.x1 - (redraw->box.x0 - redraw->xscroll))
688 < button_bar->extent.x0 ||
689 (redraw->clip.y1 - (redraw->box.y1 - redraw->yscroll))
690 < button_bar->extent.y0 ||
692 return;
693
694 icon.flags = wimp_ICON_SPRITE | wimp_ICON_INDIRECTED |
695 wimp_ICON_HCENTRED | wimp_ICON_VCENTRED;
696 if (button_bar->edit)
697 icon.flags |= wimp_ICON_BORDER | wimp_COLOUR_DARK_GREY <<
698 wimp_ICON_FG_COLOUR_SHIFT;
700 icon.flags |= wimp_ICON_FILLED | wimp_COLOUR_LIGHT_GREY <<
701 wimp_ICON_BG_COLOUR_SHIFT;
702 icon.data.indirected_sprite.id = (osspriteop_id) separator_name;
703 icon.data.indirected_sprite.area = button_bar->sprites;
704 icon.data.indirected_sprite.size = 12;
706 icon.extent.y1 = icon.extent.y0 + button_bar->y_min;
707
708 for (button = button_bar->bar; button != NULL;
709 button = button->bar_next) {
710 if (button->separator) {
711 icon.extent.x0 = button_bar->extent.x0 +
712 button->x_pos + button->x_size;
713 icon.extent.x1 = icon.extent.x0 +
715 xwimp_plot_icon(&icon);
716 }
717 }
718}
719
720
721/* This is an exported interface documented in button_bar.h */
722
724 wimp_pointer *pointer, wimp_window_state *state,
725 button_bar_action *action)
726{
727 struct button_bar_button *button;
728 os_coord pos;
729 os_box box;
730
731 if (button_bar == NULL || button_bar->hidden)
732 return false;
733
734 /* Check that the click was within our part of the window. */
735
736 pos.x = pointer->pos.x - state->visible.x0 + state->xscroll;
737 pos.y = pointer->pos.y - state->visible.y1 + state->yscroll;
738
739 if (pos.x < button_bar->extent.x0 || pos.x > button_bar->extent.x1 ||
740 pos.y < button_bar->extent.y0 ||
741 pos.y > button_bar->extent.y1)
742 return false;
743
744 if (button_bar->edit && pointer->buttons == wimp_DRAG_SELECT) {
745 /* This is an editor click, so we need to check for drags on
746 * icons (buttons) and work area (separators).
747 */
748
750 &drag_separator, NULL);
751
752 if (button != NULL && (!button->shaded || drag_separator ||
753 button_bar->edit_source != NULL)) {
754 char *sprite;
755 os_error *error;
756
758 drag_opt = button->opt_key;
759
760 if (drag_separator) {
761 box.x0 = pointer->pos.x -
765 } else {
766 box.x0 = pointer->pos.x - button->x_size / 2;
767 box.x1 = box.x0 + button->x_size;
768 sprite = button->sprite;
769 }
770
771 box.y0 = pointer->pos.y - button->y_size / 2;
772 box.y1 = box.y0 + button->y_size;
773
774 error = xdragasprite_start(dragasprite_HPOS_CENTRE |
775 dragasprite_VPOS_CENTRE |
776 dragasprite_BOUND_SPRITE |
777 dragasprite_BOUND_TO_WINDOW |
778 dragasprite_DROP_SHADOW,
780 sprite, &box, NULL);
781 if (error)
782 NSLOG(netsurf, INFO,
783 "xdragasprite_start: 0x%x: %s",
784 error->errnum,
785 error->errmess);
786
788 NULL, NULL, NULL);
789
790
791 return true;
792 }
793
794 } else if (!button_bar->edit && pointer->i != -1 &&
795 (pointer->buttons == wimp_CLICK_SELECT ||
796 pointer->buttons == wimp_CLICK_ADJUST)) {
797 /* This isn't an editor click, so we're only interested in
798 * Select or Adjust clicks that occur on physical icons.
799 */
800
801 button = ro_gui_button_bar_find_icon(button_bar, pointer->i);
802
803 if (button != NULL) {
804 if (action != NULL) {
805 switch (pointer->buttons) {
806 case wimp_CLICK_SELECT:
807 *action = button->select_action;
808 break;
809 case wimp_CLICK_ADJUST:
810 *action = button->adjust_action;
811 break;
812 default:
813 break;
814 }
815 }
816 return true;
817 }
818 }
819
820 return false;
821}
822
823
824/* This is an exported interface documented in button_bar.h */
825
827 os_coord *mouse, wimp_window_state *state,
828 wimp_mouse_state buttons, const char **suffix)
829{
830 os_coord pos;
831 struct button_bar_button *button;
832
833 if (button_bar == NULL || button_bar->hidden)
834 return false;
835
836 /* Check that the click was within our part of the window. */
837
838 pos.x = mouse->x - state->visible.x0 + state->xscroll;
839 pos.y = mouse->y - state->visible.y1 + state->yscroll;
840
841 if (pos.x < button_bar->extent.x0 || pos.x > button_bar->extent.x1 ||
842 pos.y < button_bar->extent.y0 ||
843 pos.y > button_bar->extent.y1)
844 return false;
845
846 /* Look up and return the help suffix assocuated with the button. */
847
849
850 if (button != NULL)
851 *suffix = button->help_suffix;
852 else
853 *suffix = "";
854
855 return true;
856}
857
858
859/**
860 * Terminate a drag event that was initiated by a button bar.
861 *
862 * \param *drag The drag event data.
863 * \param *data NULL data to satisfy callback syntax.
864 */
865
866void ro_gui_button_bar_drag_end(wimp_dragged *drag, void *data)
867{
868 struct button_bar *drag_end = NULL;
869 struct button_bar *source = NULL, *target = NULL;
870 struct button_bar_button *button, *drop, *previous;
871 bool right, separator;
872 wimp_window_state state;
873 wimp_pointer pointer;
874 os_coord pos;
875 os_error *error;
876
877 xdragasprite_stop();
878
879 if (drag_start == NULL)
880 return;
881
882 /* Sort out the window coordinates of the drag end. */
883
884 error = xwimp_get_pointer_info(&pointer);
885 if (error) {
886 NSLOG(netsurf, INFO, "xwimp_get_pointer_info: 0x%x: %s",
887 error->errnum, error->errmess);
888 ro_warn_user("WimpError", error->errmess);
889 return;
890 }
891
892 assert(pointer.w = drag_start->window);
893
894 state.w = drag_start->window;
895 error = xwimp_get_window_state(&state);
896 if (error) {
897 NSLOG(netsurf, INFO, "xwimp_get_window_state: 0x%x: %s",
898 error->errnum, error->errmess);
899 ro_warn_user("WimpError", error->errmess);
900 return;
901 }
902
903 pos.x = pointer.pos.x - state.visible.x0 + state.xscroll;
904 pos.y = pointer.pos.y - state.visible.y1 + state.yscroll;
905
906 /* Work out the destination bar, and establish source and target. */
907
908 if (drag_start->edit_target != NULL) {
909 source = drag_start;
910 target = drag_start->edit_target;
911 if (pos.x >= target->extent.x0 && pos.x <= target->extent.x1 &&
912 pos.y >= target->extent.y0 &&
913 pos.y <= target->extent.y1)
914 drag_end = target;
915 } else if (drag_start->edit_source != NULL) {
916 source = drag_start->edit_source;
917 target = drag_start;
918 if (pos.x >= target->extent.x0 && pos.x <= target->extent.x1 &&
919 pos.y >= target->extent.y0 &&
920 pos.y <= target->extent.y1)
921 drag_end = target;
922 /* drag_end == source and drag_end == NULL are both equivalent
923 * as far as the following code are concerned, and we don't need
924 * to identify either case. */
925 }
926
928 assert(button != NULL);
929
930 /* The drag finished in the target bar, so find out where. */
931
932 if (drag_end == target) {
933 drop = ro_gui_button_bar_find_coords(target, pos,
934 &separator, &right);
935 } else {
936 drop = NULL;
937 }
938
939 /* If the button is dropped on itself, there's no change and it's
940 * less messy to get out now.
941 */
942
943 if (drag_start == target && drag_end == target && button == drop) {
944 drag_start = NULL;
945 return;
946 }
947
948 /* The drag started in the target bar, so remove the dragged button. */
949
950 if (drag_start == target) {
951 if (drag_separator) {
952 button->separator = false;
953 } else if (target->bar == button) {
954 target->bar = button->bar_next;
955 } else {
956 for (previous = target->bar; previous != NULL &&
957 previous->bar_next != button;
958 previous = previous->bar_next);
959 assert(previous != NULL);
960 previous->bar_next = button->bar_next;
961 if (button->separator) // ??
962 previous->separator = true; // ??
963 }
964 }
965
966 /* The drag ended in the target bar, so add the dragged button in. */
967
968 if (drop != NULL) {
969 if (right) {
970 if (drag_separator) {
971 drop->separator = true;
972 } else {
973 button->bar_next = drop->bar_next;
974 drop->bar_next = button;
975 if (drop->separator && !separator) {
976 drop->separator = false;
977 button->separator = true;
978 } else {
979 button->separator = false;
980 }
981 }
982 } else if (target->bar == drop && !drag_separator) {
983 button->separator = false;
984 button->bar_next = target->bar;
985 target->bar = button;
986 } else if (target->bar != drop) {
987 for (previous = target->bar; previous != NULL &&
988 previous->bar_next != drop;
989 previous = previous->bar_next);
990 assert(previous != NULL);
991
992 if (drag_separator) {
993 previous->separator = true;
994 } else {
995 if (separator) {
996 previous->separator = false;
997 button->separator = true;
998 } else {
999 button->separator = false;
1000 }
1001 button->bar_next = previous->bar_next;
1002 previous->bar_next = button;
1003 }
1004 }
1005 }
1006
1007 /* Reposition the buttons and force our client to update. */
1008
1011 ro_gui_button_bar_sync_editors(target, source);
1012
1013 xwimp_force_redraw(target->window,
1014 target->extent.x0, target->extent.y0,
1015 target->extent.x1, target->extent.y1);
1016
1017 if (source->edit_refresh != NULL)
1018 source->edit_refresh(source->edit_client_data);
1019
1020 drag_start = NULL;
1021}
1022
1023
1024/**
1025 * Synchronise the shading of a button bar editor source bar with the currently
1026 * defined buttons in its target bar.
1027 *
1028 * \param *target The editor target bar.
1029 * \param *source The editor source bar.
1030 */
1031
1033 struct button_bar *source)
1034{
1035 struct button_bar_button *sb, *tb;
1036
1037 if (source == NULL || target == NULL)
1038 return;
1039
1040 /* Unshade all of the buttons in the source bar. */
1041
1042 for (sb = source->bar; sb != NULL; sb = sb->bar_next)
1043 sb->shaded = false;
1044
1045 /* Step through the target bar and shade each corresponding
1046 * button in the source.
1047 */
1048
1049 for (tb = target->bar; tb != NULL; tb = tb->bar_next) {
1050 sb = ro_gui_button_bar_find_opt_key(source, tb->opt_key);
1051
1052 if (sb != NULL)
1053 sb->shaded = true;
1054 }
1055
1056 /* Phyically shade the necessary buttons in the toolbar. */
1057
1058 for (sb = source->bar; sb != NULL; sb = sb->bar_next)
1059 if (sb->icon != -1)
1061 sb->shaded);
1062}
1063
1064
1065/* This is an exported interface documented in button_bar.h */
1066
1068{
1069 struct button_bar_button *button;
1070 size_t size;
1071 char *config;
1072 int i;
1073
1074 if (button_bar == NULL)
1075 return NULL;
1076
1077 for (size = 1, button = button_bar->bar; button != NULL;
1078 button = button->bar_next) {
1079 size++;
1080 if (button->separator)
1081 size++;
1082 }
1083
1084 config = malloc(size);
1085 if (config == NULL) {
1086 NSLOG(netsurf, INFO, "No memory for malloc()");
1087 ro_warn_user("NoMemory", 0);
1088 return NULL;
1089 }
1090
1091 for (i = 0, button = button_bar->bar; button != NULL;
1092 button = button->bar_next) {
1093 config[i++] = button->opt_key;
1094 if (button->separator)
1095 config[i++] = '|';
1096 }
1097
1098 config[i] = '\0';
1099
1100 return config;
1101}
1102
1103
1104/**
1105 * Find a button bar icon definition from an icon handle.
1106 *
1107 * \param *button_bar The button bar to use.
1108 * \param icon The icon handle.
1109 * \return Pointer to the button bar icon, or NULL.
1110 */
1111
1113 struct button_bar *button_bar, wimp_i icon)
1114{
1115 struct button_bar_button *button;
1116
1117 if (button_bar == NULL || icon == -1)
1118 return NULL;
1119
1120 button = button_bar->buttons;
1121
1122 while (button != NULL && button->icon != icon)
1123 button = button->next;
1124
1125 return button;
1126}
1127
1128
1129/**
1130 * Find a button bar icon definition from an options key code.
1131 *
1132 * \param *button_bar The button bar to use.
1133 * \param opt_key The option key character code.
1134 * \return Pointer to the button bar icon, or NULL.
1135 */
1136
1138 struct button_bar *button_bar, char opt_key)
1139{
1140 struct button_bar_button *button;
1141
1142 if (button_bar == NULL)
1143 return NULL;
1144
1145 button = button_bar->buttons;
1146
1147 while (button != NULL && button->opt_key != opt_key)
1148 button = button->next;
1149
1150 return button;
1151}
1152
1153
1154/**
1155 * Find a button bar icon definition from an action code.
1156 *
1157 * \param *button_bar The button bar to use.
1158 * \param action The button action to find.
1159 * \return Pointer to the button bar icon, or NULL.
1160 */
1161
1163 struct button_bar *button_bar, button_bar_action action)
1164{
1165 struct button_bar_button *button;
1166
1167 if (button_bar == NULL)
1168 return NULL;
1169
1170 button = button_bar->buttons;
1171
1172 while (button != NULL &&
1173 button->select_action != action &&
1174 button->adjust_action != action)
1175 button = button->next;
1176
1177 return button;
1178}
1179
1180
1181/**
1182 * Find a button bar icon definition from coordinates.
1183 *
1184 * \param *button_bar The button bar to use.
1185 * \param pos The coordinates to find, work area relative.
1186 * \param *separator Returns true if the associated separator was
1187 * matched; else false.
1188 * \param *right Returns true if the coordinates were in the
1189 * right hand side of the target; else false.
1190 * \return Pointer to the button bar icon, or NULL.
1191 */
1192
1194 struct button_bar *button_bar, os_coord pos,
1195 bool *separator, bool *right)
1196{
1197 struct button_bar_button *button;
1198
1199 if (button_bar == NULL)
1200 return NULL;
1201
1202 button = button_bar->bar;
1203
1204 while (button != NULL) {
1205 /* Match button extents. */
1206 int x0, y0, x1, y1;
1207
1208 x0 = button_bar->extent.x0 + button->x_pos;
1209 y0 = button_bar->extent.y0 + button->y_pos;
1210 x1 = x0 + button->x_size;
1211 y1 = y0 + button->y_size;
1212
1213 if (pos.x > x0 && pos.y > y0 && pos.x < x1 && pos.y < y1) {
1214 if (separator != NULL)
1215 *separator = false;
1216
1217 if (right != NULL)
1218 *right = (pos.x > x0 + button->x_size/2) ?
1219 true : false;
1220 return button;
1221 }
1222
1223 x0 = x1;
1224 x1 = x0 + button_bar->separator_width;
1225
1226 /* Match separator extents. */
1227
1228 if (pos.x > x0 && pos.y > y0 && pos.x < x1 && pos.y < y1 &&
1229 button->separator) {
1230 if (separator != NULL)
1231 *separator = true;
1232
1233 if (right != NULL)
1234 *right = (x0 + button_bar->separator_width/2) ?
1235 true : false;
1236 return button;
1237 }
1238
1239 button = button->bar_next;
1240 }
1241
1242 return NULL;
1243}
1244
static void ro_gui_button_bar_sync_editors(struct button_bar *target, struct button_bar *source)
Synchronise the shading of a button bar editor source bar with the currently defined buttons in its t...
Definition: button_bar.c:1032
void ro_gui_button_bar_destroy(struct button_bar *button_bar)
Destroy a button bar widget.
Definition: button_bar.c:395
static bool ro_gui_button_bar_place_buttons(struct button_bar *button_bar)
Place the buttons on a button bar, taking into account the button arrangement and the current theme,...
Definition: button_bar.c:359
static bool ro_gui_button_bar_icon_update(struct button_bar *button_bar)
Update the icons on a button bar, creating or deleting them from the window as necessary.
Definition: button_bar.c:483
static bool drag_separator
Definition: button_bar.c:106
#define BUTTONBAR_VALIDATION_LENGTH
Definition: button_bar.c:44
bool ro_gui_button_bar_help_suffix(struct button_bar *button_bar, wimp_i i, os_coord *mouse, wimp_window_state *state, wimp_mouse_state buttons, const char **suffix)
Translate mouse data into an interactive help message for a button bar.
Definition: button_bar.c:826
bool ro_gui_button_bar_arrange_buttons(struct button_bar *button_bar, char order[])
Arrange buttons on a button bar, using an order string to specify the required button and separator l...
Definition: button_bar.c:303
static struct button_bar_button * ro_gui_button_bar_find_icon(struct button_bar *button_bar, wimp_i icon)
Find a button bar icon definition from an icon handle.
Definition: button_bar.c:1112
bool ro_gui_button_bar_rebuild(struct button_bar *button_bar, struct theme_descriptor *theme, theme_style style, wimp_w window, bool edit)
Place a button bar into a toolbar window and initialise any theme-specific settings.
Definition: button_bar.c:245
static struct button_bar_button * ro_gui_button_bar_find_action(struct button_bar *button_bar, button_bar_action action)
Find a button bar icon definition from an action code.
Definition: button_bar.c:1162
struct button_bar * ro_gui_button_bar_create(struct theme_descriptor *theme, const struct button_bar_buttons buttons[])
Create a new button bar widget.
Definition: button_bar.c:130
char * ro_gui_button_bar_get_config(struct button_bar *button_bar)
Return a config string reflecting the configured order of buttons and spacers.
Definition: button_bar.c:1067
static char null_text_string[]
Definition: button_bar.c:101
bool ro_gui_button_bar_set_extent(struct button_bar *button_bar, int x0, int y0, int x1, int y1)
Set or update the dimensions to be used by the button bar, in RO units.
Definition: button_bar.c:437
bool ro_gui_button_bar_shade_button(struct button_bar *button_bar, button_bar_action action, bool shaded)
Shade or unshade a button in a bar corresponding to the given action.
Definition: button_bar.c:640
#define BUTTONBAR_SPRITE_NAME_LENGTH
Definition: button_bar.c:43
static struct button_bar * drag_start
Definition: button_bar.c:104
bool ro_gui_button_bar_link_editor(struct button_bar *target, struct button_bar *source, void(*refresh)(void *), void *client_data)
Link two button bars together.
Definition: button_bar.c:220
bool ro_gui_button_bar_get_dims(struct button_bar *button_bar, int *width, int *height)
Return the MINIMUM dimensions required by the button bar, in RO units, allowing for the current theme...
Definition: button_bar.c:416
static struct button_bar_button * ro_gui_button_bar_find_opt_key(struct button_bar *button_bar, char opt_key)
Find a button bar icon definition from an options key code.
Definition: button_bar.c:1137
void ro_gui_button_bar_redraw(struct button_bar *button_bar, wimp_draw *redraw)
Handle redraw event rectangles in a button bar.
Definition: button_bar.c:672
bool ro_gui_button_bar_hide(struct button_bar *button_bar, bool hide)
Show or hide a button bar.
Definition: button_bar.c:627
static char separator_name[]
Definition: button_bar.c:102
static bool ro_gui_button_bar_icon_resize(struct button_bar *button_bar)
Position the icons in the button bar to take account of the currently configured extent.
Definition: button_bar.c:581
static struct button_bar_button * ro_gui_button_bar_find_coords(struct button_bar *button_bar, os_coord pos, bool *separator, bool *right)
Find a button bar icon definition from coordinates.
Definition: button_bar.c:1193
static char drag_opt
Definition: button_bar.c:105
bool ro_gui_button_bar_click(struct button_bar *button_bar, wimp_pointer *pointer, wimp_window_state *state, button_bar_action *action)
Handle mouse clicks in a button bar.
Definition: button_bar.c:723
static void ro_gui_button_bar_drag_end(wimp_dragged *drag, void *data)
Terminate a drag event that was initiated by a button bar.
Definition: button_bar.c:866
Button bars (interface).
button_bar_action
Definition: button_bar.h:32
void ro_mouse_drag_start(void(*drag_end)(wimp_dragged *dragged, void *data), void(*drag_track)(wimp_pointer *pointer, void *data), void(*drag_cancel)(void *data), void *data)
Start a drag, providing a function to be called when the Wimp_DragEnd event is received and optionall...
Definition: mouse.c:115
Mouse dragging and tracking support interface for RISC OS.
Window themes(interface).
@ THEME_ELEMENT_BACKGROUND
Definition: theme.h:44
theme_style
Theme styles, collecting groups of attributes for different locations.
Definition: theme.h:31
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
int width
Definition: gui.c:160
nserror ro_warn_user(const char *warning, const char *detail)
Display a warning for a serious problem (eg memory exhaustion).
Definition: gui.c:2077
int height
Definition: gui.c:161
osspriteop_area * ro_gui_theme_get_sprites(struct theme_descriptor *descriptor)
Returns a sprite area for use with the given theme.
Definition: theme.c:221
int ro_gui_theme_get_style_element(struct theme_descriptor *descriptor, theme_style style, theme_element element)
Returns an interger element from the specified theme, or the current theme if the descriptor is NULL.
Definition: theme.c:251
Interface to utility string handling.
Node in box tree.
Definition: box.h:177
int x
Coordinate of left padding edge relative to parent box, or relative to ancestor that contains this bo...
Definition: box.h:280
int y
Coordinate of top padding edge, relative as for x.
Definition: box.h:284
button_bar_action adjust_action
Definition: button_bar.c:52
char sprite[BUTTONBAR_SPRITE_NAME_LENGTH]
Definition: button_bar.c:57
char validation[BUTTONBAR_VALIDATION_LENGTH]
Definition: button_bar.c:58
struct button_bar_button * bar_next
Definition: button_bar.c:62
struct button_bar_button * next
Definition: button_bar.c:63
button_bar_action select_action
Definition: button_bar.c:51
const char * help_suffix
Definition: button_bar.c:60
const char * icon
The sprite used for the icon.
Definition: button_bar.h:72
const char * help
The interactive help token.
Definition: button_bar.h:76
button_bar_action select
The action for select clicks.
Definition: button_bar.h:73
const char opt_key
The char used in option strings.
Definition: button_bar.h:75
button_bar_action adjust
The action for Adjust clicks.
Definition: button_bar.h:74
bool hidden
Definition: button_bar.c:84
void * edit_client_data
Definition: button_bar.c:90
bool edit
Definition: button_bar.c:86
wimp_w window
The window details and bar position.
Definition: button_bar.c:79
void(* edit_refresh)(void *)
Definition: button_bar.c:89
bool separators
Definition: button_bar.c:76
int vertical_offset
Definition: button_bar.c:74
struct theme_descriptor * theme
The applied theme (or NULL to use the default)
Definition: button_bar.c:69
os_box extent
Definition: button_bar.c:80
int separator_width
Definition: button_bar.c:73
struct button_bar_button * bar
The list of the buttons in the current bar.
Definition: button_bar.c:98
struct button_bar_button * buttons
The list of all the defined buttons.
Definition: button_bar.c:94
osspriteop_area * sprites
Definition: button_bar.c:81
struct button_bar * edit_target
Definition: button_bar.c:87
struct button_bar * edit_source
Definition: button_bar.c:88
int background
Definition: button_bar.c:82
int x_min
The widget dimensions.
Definition: button_bar.c:72
Definition: theme.h:64
bool ro_gui_wimp_get_sprite_dimensions(osspriteop_area *area, char *sprite, int *width, int *height)
Get the dimensions of a sprite.
Definition: wimp.c:925
void ro_gui_set_icon_shaded_state(wimp_w w, wimp_i i, bool state)
Set the shaded state of an icon.
Definition: wimp.c:487
General RISC OS WIMP/OS library functions (interface).