1 | package Uploader::GUI::wxCategoryTreeCtrl; |
---|
2 | use strict; |
---|
3 | use Wx; |
---|
4 | use Wx::DND; |
---|
5 | use base qw/Wx::TreeCtrl Class::Accessor::Fast/; |
---|
6 | |
---|
7 | use Wx qw/ |
---|
8 | wxTheApp |
---|
9 | wxBITMAP_TYPE_PNG |
---|
10 | wxDefaultPosition |
---|
11 | wxDefaultSize |
---|
12 | wxALIGN_CENTER |
---|
13 | wxALL |
---|
14 | wxSWISS |
---|
15 | wxNORMAL |
---|
16 | wxVERTICAL |
---|
17 | wxBOLD |
---|
18 | wxWHITE |
---|
19 | wxID_CANCEL |
---|
20 | /; |
---|
21 | |
---|
22 | __PACKAGE__->mk_accessors( |
---|
23 | qw/ |
---|
24 | wx_img |
---|
25 | categories |
---|
26 | root |
---|
27 | selection_ids |
---|
28 | frame_callback |
---|
29 | / |
---|
30 | ); |
---|
31 | use Data::Dumper; |
---|
32 | |
---|
33 | |
---|
34 | sub new { |
---|
35 | my( $class, $params ) = @_; |
---|
36 | |
---|
37 | my( $self ) = $class->SUPER::new( |
---|
38 | $params->{parentwnd}, |
---|
39 | $params->{id}||-1, |
---|
40 | $params->{position}||wxDefaultPosition, |
---|
41 | $params->{size}||[ -1, -1], |
---|
42 | ); |
---|
43 | |
---|
44 | $self->categories( |
---|
45 | $params->{categories} |
---|
46 | ); |
---|
47 | |
---|
48 | $self->selection_ids( |
---|
49 | $params->{selection_ids} |
---|
50 | ); |
---|
51 | |
---|
52 | $self->frame_callback( |
---|
53 | $params->{frame_callback} |
---|
54 | ); |
---|
55 | |
---|
56 | |
---|
57 | $self->init_bitmaps; |
---|
58 | $self->init_empty_category_msg; |
---|
59 | $self->init_empty_category_evt; |
---|
60 | |
---|
61 | if(wxTheApp->use_offline){ |
---|
62 | $self->Enable(0); |
---|
63 | } |
---|
64 | else{ |
---|
65 | $self->Populate; |
---|
66 | } |
---|
67 | |
---|
68 | |
---|
69 | $self; |
---|
70 | } |
---|
71 | |
---|
72 | |
---|
73 | sub ShowEmptyMsg { |
---|
74 | my ( $self ) = @_; |
---|
75 | |
---|
76 | $self->{_empty_panel}->Show; |
---|
77 | } |
---|
78 | |
---|
79 | |
---|
80 | sub HideEmptyMsg { |
---|
81 | my ( $self ) = @_; |
---|
82 | |
---|
83 | $self->{_empty_panel}->Hide; |
---|
84 | } |
---|
85 | |
---|
86 | |
---|
87 | sub init_bitmaps{ |
---|
88 | my ( $self ) = @_; |
---|
89 | |
---|
90 | $self->wx_img( |
---|
91 | Wx::ImageList->new( 16, 16, 1 ) |
---|
92 | ); |
---|
93 | |
---|
94 | |
---|
95 | map { |
---|
96 | $self->wx_img->Add( |
---|
97 | Wx::Bitmap->new( $_, wxBITMAP_TYPE_PNG ) |
---|
98 | ); |
---|
99 | } |
---|
100 | ( |
---|
101 | wxTheApp->resource_path('tree_pwg.png'), |
---|
102 | wxTheApp->resource_path('tree_folder.png'), |
---|
103 | ); |
---|
104 | |
---|
105 | $self->SetImageList( $self->wx_img ); |
---|
106 | } |
---|
107 | |
---|
108 | |
---|
109 | sub itemData { Wx::TreeItemData->new( $_[0] ) } |
---|
110 | |
---|
111 | |
---|
112 | sub Populate { |
---|
113 | my ( $self ) = @_; |
---|
114 | |
---|
115 | my $tree_items = $self->categories; |
---|
116 | my $root = shift @{$tree_items}; |
---|
117 | |
---|
118 | $self->root( |
---|
119 | $self->AddRoot( |
---|
120 | $root->[0], |
---|
121 | $root->[3], |
---|
122 | $root->[4], |
---|
123 | itemData( $root->[2] ) |
---|
124 | ) |
---|
125 | ); |
---|
126 | |
---|
127 | $self->populate_tree_helper( $self->root, $tree_items ); |
---|
128 | |
---|
129 | $self->Expand( $self->root ); |
---|
130 | } |
---|
131 | |
---|
132 | sub populate_tree_helper { |
---|
133 | my ( $self, $parent_id, $tree_items ) = @_; |
---|
134 | |
---|
135 | my $id; |
---|
136 | |
---|
137 | map { |
---|
138 | my $name = $_->[0]; |
---|
139 | |
---|
140 | $id = $self->AppendItem( |
---|
141 | $parent_id, |
---|
142 | $name, |
---|
143 | defined($_->[3]) ? $_->[3] : 0, |
---|
144 | defined($_->[4]) ? $_->[4] : 0, |
---|
145 | itemData( $_->[2]) |
---|
146 | ); |
---|
147 | # current item has children |
---|
148 | if( ref( $_->[1] ) eq 'ARRAY' ) { |
---|
149 | $self->populate_tree_helper( $id, $_->[1] ); |
---|
150 | } |
---|
151 | } |
---|
152 | @{$tree_items}; |
---|
153 | |
---|
154 | } |
---|
155 | |
---|
156 | |
---|
157 | sub init_empty_category_msg { |
---|
158 | |
---|
159 | my ( $self ) = @_; |
---|
160 | # add a panel |
---|
161 | my $empty_panel = Wx::Panel->new($self, -1, wxDefaultPosition, wxDefaultSize); |
---|
162 | my( $item0 ) = Wx::BoxSizer->new( wxVERTICAL ); |
---|
163 | |
---|
164 | my $fb = Wx::Font->new( 12, wxSWISS, wxNORMAL, wxBOLD ); |
---|
165 | |
---|
166 | |
---|
167 | my( $item1 ) = Wx::Button->new( |
---|
168 | $empty_panel, |
---|
169 | $main::CATEGORIES_ADD, |
---|
170 | wxTheApp->branding->{'Add new category'}, |
---|
171 | wxDefaultPosition, |
---|
172 | [-1,40], |
---|
173 | 0 |
---|
174 | ); |
---|
175 | my $btfont = Wx::Font->new(12, wxSWISS, wxNORMAL, wxNORMAL ); |
---|
176 | $item1->SetFont($btfont); |
---|
177 | $item0->AddWindow( $item1, 0, wxALIGN_CENTER|wxALL, 5 ); |
---|
178 | |
---|
179 | |
---|
180 | $empty_panel->SetSizer( $item0 ); |
---|
181 | $item0->SetSizeHints( $empty_panel ); |
---|
182 | |
---|
183 | $self->{_empty_panel} = $empty_panel; |
---|
184 | $self->{_empty_panel}->SetBackgroundColour(wxWHITE); |
---|
185 | |
---|
186 | my ($wp, $hp) = $self->{_empty_panel}->GetSizeWH; |
---|
187 | |
---|
188 | $self->SetMinSize( [20+$wp, -1 ]); |
---|
189 | |
---|
190 | Wx::Event::EVT_BUTTON( $self, $main::CATEGORIES_ADD, \&AddCategory ); |
---|
191 | } |
---|
192 | |
---|
193 | |
---|
194 | sub init_empty_category_evt{ |
---|
195 | my ( $self ) = @_; |
---|
196 | |
---|
197 | Wx::Event::EVT_PAINT( $self, sub { |
---|
198 | my ( $tree, $event ) = @_; |
---|
199 | if(exists $tree->{_empty_panel} and ! exists $tree->{_empty_panel}{_paint}){ |
---|
200 | my ($w, $h) = $tree->GetSizeWH; |
---|
201 | my ($x, $y) = $tree->{_empty_panel}->GetPositionXY; |
---|
202 | |
---|
203 | $tree->{_empty_panel}{x} = $x if !exists $tree->{_empty_panel}{x} ; |
---|
204 | $tree->{_empty_panel}{y} = $y if !exists $tree->{_empty_panel}{y}; |
---|
205 | my ($wp, $hp) = $tree->{_empty_panel}->GetSizeWH; |
---|
206 | my $x_off = ($w-$wp)/2 > 0 ? ($w-$wp)/2 : 0; |
---|
207 | my $y_off = ($h-$hp)/2 > 0 ? ($h-$hp)/2 : 0; |
---|
208 | $tree->{_empty_panel}->Move( |
---|
209 | [ |
---|
210 | $tree->{_empty_panel}{x}+$x_off, |
---|
211 | $tree->{_empty_panel}{y}+$y_off |
---|
212 | ] |
---|
213 | ); |
---|
214 | $tree->{_empty_panel}{_paint} = 1; |
---|
215 | } |
---|
216 | $event->Skip; |
---|
217 | } |
---|
218 | ); |
---|
219 | |
---|
220 | } |
---|
221 | |
---|
222 | |
---|
223 | sub GetSelectionsIds { |
---|
224 | my ( $self )=@_; |
---|
225 | |
---|
226 | |
---|
227 | return [ |
---|
228 | grep { defined $_ } |
---|
229 | map { |
---|
230 | my $category = $self->GetPlData( $_ ); |
---|
231 | $category != -1 ? |
---|
232 | $category->{id} : |
---|
233 | undef ; |
---|
234 | } |
---|
235 | ( $self->GetSelections ) |
---|
236 | ]; |
---|
237 | } |
---|
238 | |
---|
239 | |
---|
240 | sub AddCategory { |
---|
241 | my ( $self, $event ) = @_; |
---|
242 | |
---|
243 | $self->SelectDefaultParent; |
---|
244 | |
---|
245 | my $parent_category_id = $self->GetSelectionsIds->[0]; |
---|
246 | my $parent_item = $self->GetSelection; |
---|
247 | |
---|
248 | my $dialog = Wx::TextEntryDialog->new( |
---|
249 | $self, |
---|
250 | wxTheApp->branding->{'Category name'}, |
---|
251 | wxTheApp->branding->{'Add new category'}, |
---|
252 | wxTheApp->branding->{'New category'}, |
---|
253 | ); |
---|
254 | |
---|
255 | if( $dialog->ShowModal != wxID_CANCEL ) { |
---|
256 | my $name = $dialog->GetValue; |
---|
257 | my ( $success, $status_msg, $content ) = wxTheApp->pwg->AddCategories( $name, $parent_category_id); |
---|
258 | |
---|
259 | if($success){ |
---|
260 | $self->_append_category($parent_item, $name, $content->{result}{id}); |
---|
261 | # direct, without test on pwg_categories |
---|
262 | # because of lazy refresh to avoid re-populating the whole tree |
---|
263 | $self->ShowHideEmptyCategoriesMsg; |
---|
264 | $self->frame_callback->() if 'CODE' eq ref $self->frame_callback; |
---|
265 | } |
---|
266 | } |
---|
267 | |
---|
268 | $dialog->Destroy; |
---|
269 | } |
---|
270 | |
---|
271 | |
---|
272 | sub SelectDefaultParent { |
---|
273 | my ( $self ) = @_; |
---|
274 | |
---|
275 | if(!scalar @{$self->GetSelectionsIds}){ |
---|
276 | $self->SelectItem($self->GetRootItem); |
---|
277 | } |
---|
278 | } |
---|
279 | |
---|
280 | sub ShowHideEmptyCategoriesMsg { |
---|
281 | my ( $self ) = @_; |
---|
282 | |
---|
283 | $self->GetCount > 1 ? |
---|
284 | $self->HideEmptyMsg : |
---|
285 | $self->ShowEmptyMsg; |
---|
286 | } |
---|
287 | |
---|
288 | |
---|
289 | sub _append_category { |
---|
290 | my ( $self, $parent_id, $name, $id ) = @_; |
---|
291 | |
---|
292 | $self->SelectItem( |
---|
293 | $self->AppendItem( |
---|
294 | $parent_id, |
---|
295 | $name, |
---|
296 | 1, |
---|
297 | -1, |
---|
298 | Wx::TreeItemData->new( { id => $id } ) |
---|
299 | ) |
---|
300 | ); |
---|
301 | } |
---|
302 | |
---|
303 | 1; |
---|