1 | // ============================================================ // |
---|
2 | // // |
---|
3 | // File : NT_shadeTree.cxx // |
---|
4 | // Purpose : // |
---|
5 | // // |
---|
6 | // Coded by Ralf Westram (coder@reallysoft.de) in June 2016 // |
---|
7 | // http://www.arb-home.de/ // |
---|
8 | // // |
---|
9 | // ============================================================ // |
---|
10 | |
---|
11 | #include "tree_position.h" |
---|
12 | |
---|
13 | #include <TreeDisplay.hxx> |
---|
14 | #include <AP_TreeShader.hxx> |
---|
15 | |
---|
16 | #include <awt_canvas.hxx> |
---|
17 | |
---|
18 | #include <aw_root.hxx> |
---|
19 | #include <aw_awar.hxx> |
---|
20 | #include <aw_awar_defs.hxx> |
---|
21 | |
---|
22 | #define nt_assert(cond) arb_assert(cond) |
---|
23 | |
---|
24 | // ------------------------ |
---|
25 | // TopologyShader |
---|
26 | |
---|
27 | typedef SmartPtr<TreePositionLookup> TreePositionLookupPtr; |
---|
28 | |
---|
29 | class TopologyShader: public ShaderPlugin { |
---|
30 | RefPtr<AWT_graphic_tree> agt; |
---|
31 | mutable TreePositionLookupPtr pos; |
---|
32 | |
---|
33 | void init_specific_awars(AW_root*) OVERRIDE {} |
---|
34 | |
---|
35 | void update_pos_lookup() const { |
---|
36 | pos = new TreePositionLookup(agt->get_logical_root()); |
---|
37 | } |
---|
38 | |
---|
39 | public: |
---|
40 | TopologyShader(AWT_graphic_tree *agt_) : |
---|
41 | ShaderPlugin("topology", "Topology shader"), |
---|
42 | agt(agt_) |
---|
43 | {} |
---|
44 | |
---|
45 | ShadedValue shade(GBDATA *gb_item) const OVERRIDE { |
---|
46 | if (gb_item) { |
---|
47 | if (pos.isNull()) update_pos_lookup(); |
---|
48 | |
---|
49 | const char *name = GBT_get_name(gb_item); |
---|
50 | if (name) { |
---|
51 | TreeRelativePosition relpos = pos->relative(name); |
---|
52 | if (relpos.is_known()) return ValueTuple::make(relpos.value()); |
---|
53 | } |
---|
54 | } |
---|
55 | return ValueTuple::undefined(); |
---|
56 | } |
---|
57 | |
---|
58 | int get_dimension() const OVERRIDE { return 1; } |
---|
59 | bool customizable() const OVERRIDE { return true; } |
---|
60 | void customize(AW_root *) OVERRIDE { AW_help_popup(NULp, "topology_shader.hlp"); } |
---|
61 | |
---|
62 | char *store_config() const OVERRIDE { return NULp; } |
---|
63 | void load_or_reset_config(const char *) OVERRIDE {} |
---|
64 | |
---|
65 | void activate(bool on) OVERRIDE; |
---|
66 | |
---|
67 | #if defined(ASSERTION_USED) |
---|
68 | bool is_linked_with(AWT_graphic_tree *linkedWith) { return linkedWith == agt; } |
---|
69 | #endif |
---|
70 | |
---|
71 | void tree_changed_cb() { |
---|
72 | pos.setNull(); |
---|
73 | trigger_reshade_if_active_cb(SIMPLE_RESHADE); // forces reshade of "other" tree-canvas |
---|
74 | } |
---|
75 | static void tree_changed_cb(AWT_graphic_tree *IF_ASSERTION_USED(by), TopologyShader *shader) { |
---|
76 | nt_assert(shader->is_linked_with(by)); |
---|
77 | shader->tree_changed_cb(); |
---|
78 | } |
---|
79 | }; |
---|
80 | |
---|
81 | void TopologyShader::activate(bool on) { |
---|
82 | // called with true when plugin gets activated, with false when it gets deactivated |
---|
83 | |
---|
84 | if (on) { |
---|
85 | pos.setNull(); // invalidate cached positions |
---|
86 | GraphicTreeCallback gtcb = makeGraphicTreeCallback(TopologyShader::tree_changed_cb, this); |
---|
87 | agt->install_tree_changed_callback(gtcb); |
---|
88 | } |
---|
89 | else { |
---|
90 | agt->uninstall_tree_changed_callback(); |
---|
91 | } |
---|
92 | } |
---|
93 | |
---|
94 | // ----------------------- |
---|
95 | // NT_TreeShader |
---|
96 | |
---|
97 | class NT_TreeShader: public AP_TreeShader, virtual Noncopyable { |
---|
98 | ItemShader *shader; // (owned by registry in ITEM_SHADER) |
---|
99 | |
---|
100 | static void reshade() { |
---|
101 | #if defined(DEBUG) |
---|
102 | fprintf(stderr, "[NT_TreeShader::reshade] @ %zu\n", clock()); |
---|
103 | #endif |
---|
104 | AW_root::SINGLETON->awar(AWAR_TREE_RECOMPUTE)->touch(); |
---|
105 | } |
---|
106 | |
---|
107 | public: |
---|
108 | NT_TreeShader(TREE_canvas *ntw, GBDATA *gb_main) : |
---|
109 | shader(registerItemShader(ntw->awr, |
---|
110 | ntw->gc_manager, |
---|
111 | BoundItemSel(gb_main, SPECIES_get_selector()), |
---|
112 | "tree", |
---|
113 | "Tree shading", |
---|
114 | "tree_shading.hlp", |
---|
115 | NT_TreeShader::reshade, |
---|
116 | AWT_GC_NONE_MARKED)) |
---|
117 | { |
---|
118 | AWT_graphic_tree *agt = DOWNCAST(AWT_graphic_tree*, ntw->gfx); |
---|
119 | ShaderPluginPtr topo_shader = new TopologyShader(agt); |
---|
120 | shader->register_plugin(topo_shader); |
---|
121 | } |
---|
122 | ~NT_TreeShader() OVERRIDE {} |
---|
123 | void init() OVERRIDE { shader->init(); } // called by AP_tree::set_tree_shader when installed |
---|
124 | |
---|
125 | void update_settings() OVERRIDE { |
---|
126 | colorize_marked = shader->overlay_marked(); |
---|
127 | colorize_groups = shader->overlay_color_groups(); |
---|
128 | shade_species = shader->active(); |
---|
129 | } |
---|
130 | |
---|
131 | ShadedValue calc_shaded_leaf_GC(GBDATA *gb_node) const OVERRIDE { return shader->shade(gb_node); } |
---|
132 | ShadedValue calc_shaded_inner_GC(const ShadedValue& left, float left_ratio, const ShadedValue& right) const OVERRIDE { |
---|
133 | return mix(left, left_ratio, right); |
---|
134 | } |
---|
135 | int to_GC(const ShadedValue& val) const OVERRIDE { return shader->to_GC(val); } |
---|
136 | |
---|
137 | void popup_config() const { |
---|
138 | shader->popup_config_window(AW_root::SINGLETON); |
---|
139 | } |
---|
140 | }; |
---|
141 | |
---|
142 | // ---------------------------- |
---|
143 | // external interface |
---|
144 | |
---|
145 | void NT_install_treeShader(TREE_canvas *ntw, GBDATA *gb_main) { |
---|
146 | AP_tree::set_tree_shader(new NT_TreeShader(ntw, gb_main)); |
---|
147 | } |
---|
148 | |
---|
149 | void NT_configure_treeShader() { |
---|
150 | const AP_TreeShader *tshader = AP_tree::get_tree_shader(); |
---|
151 | nt_assert(tshader); |
---|
152 | if (tshader) DOWNCAST(const NT_TreeShader*, tshader)->popup_config(); |
---|
153 | |
---|
154 | } |
---|
155 | |
---|
156 | |
---|
157 | |
---|