| 65 |
65 |
| 66 ctx->documents = cxLinkedListCreate(mp->allocator, CX_STORE_POINTERS); |
66 ctx->documents = cxLinkedListCreate(mp->allocator, CX_STORE_POINTERS); |
| 67 ctx->state_widgets = cxLinkedListCreate(mp->allocator, sizeof(UiStateWidget)); |
67 ctx->state_widgets = cxLinkedListCreate(mp->allocator, sizeof(UiStateWidget)); |
| 68 ctx->states = cxArrayListCreate(mp->allocator, sizeof(int), 32); |
68 ctx->states = cxArrayListCreate(mp->allocator, sizeof(int), 32); |
| 69 cxSetCompareFunc(ctx->states, cx_cmp_int); |
69 cxSetCompareFunc(ctx->states, cx_cmp_int); |
| |
70 ctx->suppressed_states = cxArrayListCreate(mp->allocator, sizeof(int), 16); |
| |
71 cxSetCompareFunc(ctx->suppressed_states, cx_cmp_int); |
| 70 |
72 |
| 71 ctx->actions = cxHashMapCreate(ctx->allocator, sizeof(UiAction), 8); |
73 ctx->actions = cxHashMapCreate(ctx->allocator, sizeof(UiAction), 8); |
| 72 ctx->action_bindings = cxArrayListCreate(ctx->allocator, sizeof(UiActionBinding), 0); |
74 ctx->action_bindings = cxArrayListCreate(ctx->allocator, sizeof(UiActionBinding), 0); |
| 73 |
75 |
| 74 #if UI_GTK2 || UI_GTK3 |
76 #if UI_GTK2 || UI_GTK3 |
| 680 |
682 |
| 681 // enable/disable group widgets |
683 // enable/disable group widgets |
| 682 uic_check_state_widgets(ui_context_toplevel_parent(ctx)); |
684 uic_check_state_widgets(ui_context_toplevel_parent(ctx)); |
| 683 } |
685 } |
| 684 |
686 |
| |
687 void ui_suppress_state(UiContext *ctx, int state) { |
| |
688 if(!cxListIndexValid(ctx->suppressed_states, cxListFind(ctx->suppressed_states, &state))) { |
| |
689 cxListAdd(ctx->suppressed_states, &state); |
| |
690 } |
| |
691 |
| |
692 // enable/disable group widgets |
| |
693 uic_check_state_widgets(ui_context_toplevel_parent(ctx)); |
| |
694 } |
| |
695 |
| |
696 void ui_unsuppress_state(UiContext *ctx, int state) { |
| |
697 int i = cxListFind(ctx->suppressed_states, &state); |
| |
698 if(i != -1) { |
| |
699 cxListRemove(ctx->suppressed_states, i); |
| |
700 } |
| |
701 |
| |
702 // enable/disable group widgets |
| |
703 uic_check_state_widgets(ui_context_toplevel_parent(ctx)); |
| |
704 } |
| |
705 |
| 685 typedef struct StatesList { |
706 typedef struct StatesList { |
| 686 CX_ARRAY(int, states); |
707 CX_ARRAY(int, states); |
| |
708 CX_ARRAY(int, suppressed); |
| 687 } StatesList; |
709 } StatesList; |
| 688 |
710 |
| 689 static void add_ctx_states(UiContext *ctx, StatesList *states) { |
711 static void add_ctx_states(UiContext *ctx, StatesList *states) { |
| 690 size_t nstates = cxListSize(ctx->states); |
712 size_t nstates = cxListSize(ctx->states); |
| 691 int *ctx_states = cxListAt(ctx->states, 0);; |
713 int *ctx_states = cxListAt(ctx->states, 0); |
| |
714 |
| |
715 size_t nsuppressed = cxListSize(ctx->suppressed_states); |
| |
716 int *ctx_suppressed_states = cxListAt(ctx->suppressed_states, 0); |
| 692 |
717 |
| 693 cx_array_add_array(states->states, ctx_states, nstates); |
718 cx_array_add_array(states->states, ctx_states, nstates); |
| |
719 cx_array_add_array(states->suppressed, ctx_suppressed_states, nsuppressed); |
| 694 |
720 |
| 695 CxIterator i = cxListIterator(ctx->documents); |
721 CxIterator i = cxListIterator(ctx->documents); |
| 696 cx_foreach(void *, doc, i) { |
722 cx_foreach(void *, doc, i) { |
| 697 UiContext *doc_ctx = ui_document_context(doc); |
723 UiContext *doc_ctx = ui_document_context(doc); |
| 698 add_ctx_states(doc_ctx, states); |
724 add_ctx_states(doc_ctx, states); |
| 700 } |
726 } |
| 701 |
727 |
| 702 int* ui_active_states(UiContext *ctx, int *nstates) { |
728 int* ui_active_states(UiContext *ctx, int *nstates) { |
| 703 StatesList states; |
729 StatesList states; |
| 704 cx_array_init(states.states, 32); |
730 cx_array_init(states.states, 32); |
| |
731 cx_array_init(states.suppressed, 8); |
| 705 add_ctx_states(ctx, &states); |
732 add_ctx_states(ctx, &states); |
| |
733 |
| |
734 // remove suppressed states |
| |
735 for(size_t i=0;i<states.suppressed.size;i++) { |
| |
736 int suppressed = states.suppressed.data[i]; |
| |
737 // important to use ssize_t for the index here |
| |
738 for(ssize_t s=0;s<states.states.size;s++) { |
| |
739 if(states.states.data[s] == suppressed) { |
| |
740 // this state is suppressed |
| |
741 if(s+1 < states.states.size) { |
| |
742 // copy last element to the current position |
| |
743 states.states.data[s] = states.states.data[states.states.size-1]; |
| |
744 // we need to check the current index again |
| |
745 s--; |
| |
746 } |
| |
747 states.states.size--; |
| |
748 } |
| |
749 } |
| |
750 } |
| |
751 |
| |
752 free(states.suppressed.data); |
| 706 *nstates = (int)states.states.size; |
753 *nstates = (int)states.states.size; |
| 707 return states.states.data; |
754 return states.states.data; |
| 708 } |
755 } |
| 709 |
756 |
| 710 void uic_check_state_widgets(UiContext *ctx) { |
757 void uic_check_state_widgets(UiContext *ctx) { |
| 711 if(!ctx) { |
758 if(!ctx) { |
| 712 return; |
759 return; |
| 713 } |
760 } |
| 714 |
761 |
| 715 int ngroups = 0; |
762 int nstates = 0; |
| 716 int *groups = ui_active_states(ctx, &ngroups); |
763 int *states = ui_active_states(ctx, &nstates); |
| 717 |
764 |
| 718 CxIterator i = cxListIterator(ctx->state_widgets); |
765 CxIterator i = cxListIterator(ctx->state_widgets); |
| 719 cx_foreach(UiStateWidget *, gw, i) { |
766 cx_foreach(UiStateWidget *, gw, i) { |
| 720 char *check = calloc(1, gw->numstates); |
767 char *check = calloc(1, gw->numstates); |
| 721 |
768 |
| 722 for(int i=0;i<ngroups;i++) { |
769 for(int i=0;i<nstates;i++) { |
| 723 for(int k=0;k<gw->numstates;k++) { |
770 for(int k=0;k<gw->numstates;k++) { |
| 724 if(groups[i] == gw->states[k]) { |
771 if(states[i] == gw->states[k]) { |
| 725 check[k] = 1; |
772 check[k] = 1; |
| 726 } |
773 } |
| 727 } |
774 } |
| 728 } |
775 } |
| 729 |
776 |