ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/DC/UI/Dockbar.pm
Revision: 1.9
Committed: Sat Apr 3 02:58:25 2010 UTC (14 years, 1 month ago) by root
Branch: MAIN
CVS Tags: rel-2_11, HEAD
Changes since 1.8: +2 -3 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 package DC::UI::Dockbar;
2
3 use common::sense;
4
5 use DC::UI::Dockable;
6
7 our @ISA = DC::UI::Toplevel::;
8
9 sub new {
10 my $class = shift;
11
12 my $self = $class->SUPER::new (
13 border_bg => [1, 1, 1, 1],
14 x => "max",
15 y => 0,
16 child => (my $nb = DC::UI::Notebook->new (expand => 1)),
17 @_,
18 );
19
20 $self->{notebook} = $nb;
21
22 $nb->connect (page_changed => sub {
23 my ($nb, $page) = @_;
24 $self->update_active ($page);
25 0
26 });
27
28 $self
29 }
30
31 # This method is which you want to call to add a Dockable
32 sub add_dock {
33 my ($self, $dockable) = @_;
34 $self->{docks}->{"$dockable"} = $dockable;
35 delete $self->{dock_windows}->{"$dockable"};
36
37 $dockable->set_dockbar ($self);
38
39 # TODO: capture the guards to remove these connections
40 $dockable->connect (dock => sub {
41 my ($dockable) = @_;
42 #d# warn "DOCKABLE DOCK";
43 $self->dock ($dockable);
44 0
45 });
46
47 $dockable->connect (undock => sub {
48 my ($dockable) = @_;
49 #d# warn "DOCKABLE UNDOCK";
50 $self->undock ($dockable);
51 0
52 });
53
54 $dockable->connect (close_dock => sub {
55 my ($dockable) = @_;
56 $self->remove_dock ($dockable);
57 0
58 });
59
60 $self->dock ($dockable);
61 }
62
63 # This method will remove the dockable from the Dockbar. Which means that the
64 # window for this dockable is also removed (if it was undocked).
65 sub remove_dock {
66 my ($self, $dockable) = @_;
67
68 $self->undock_window ($dockable);
69 $self->undock_notebook ($dockable);
70 delete $self->{docks}->{"$dockable"};
71 $dockable->set_dockbar (undef);
72 }
73
74 # This method makes sure the dockable is 'docked' into the Dockbar
75 # and eg. removes the free floating window it maybe has.
76 sub dock {
77 my ($self, $dockable) = @_;
78 $self->undock_window ($dockable);
79
80 # here the assumption is done that $dockable is inserted at the end of the
81 # notebook tabs, so that the other tabs dont have to be updated
82 $self->{notebook}->add ($dockable);
83 $dockable->set_dockbar_pos ($self->{notebook}->page_index ($dockable));
84 $self->update_active;
85 }
86
87 # (private) This method updates all docked tabs and tells them whether their
88 # tab is 'active'.
89 sub update_active {
90 my ($self, $page) = @_;
91
92 unless ($page) {
93 $page = $self->{notebook}->get_current_page;
94 }
95
96 for ($self->{notebook}->pages) {
97 $_->set_dockbar_tab_active ($_ eq $page);
98 }
99 }
100
101 # This method undocks the dockable (if it isn't already undocked) and
102 # creates a floating window for it.
103 sub undock {
104 my ($self, $dockable) = @_;
105 return if $self->{dock_windows}->{"$dockable"};
106
107 $self->undock_notebook ($dockable);
108 my $win =
109 $self->{dock_windows}->{"$dockable"} =
110 DC::UI::Toplevel->new (
111 title => $dockable->get_title,
112 child => $dockable,
113 force_w => 100, force_h => 100,
114 x => 100, y => 100,
115 has_close_button => 1,
116 );
117
118 $win->connect (delete => sub {
119 $self->dock ($dockable);
120 0
121 });
122
123 $win->show;
124 }
125
126 # (private) This method does the cleanup stuff when the dockable is docked
127 # into the dockbar and had a floating window.
128 sub undock_window {
129 my ($self, $dockable) = @_;
130 my $win =
131 $self->{dock_windows}->{"$dockable"}
132 or return;
133
134 $win->remove ($dockable);
135 delete $self->{dock_windows}->{"$dockable"};
136 $win->hide; # XXX: neccessary?
137 }
138
139 # (private) This method does the cleanup stuff which is neccessary when the
140 # dockable is removed from the notebook.
141 sub undock_notebook {
142 my ($self, $dockable) = @_;
143 $self->{notebook}->remove ($dockable);
144 my $nextpage = ($self->{notebook}->pages)[0];
145 $self->{notebook}->set_current_page ($nextpage)
146 if $nextpage;
147 $dockable->set_dockbar_pos (undef);
148 $dockable->set_dockbar_tab_active (undef);
149 $self->update_dockbar_positions;
150 }
151
152 # (private) This method updates the position of the dockables in the dockbar.
153 sub update_dockbar_positions {
154 my ($self) = @_;
155 my $i = 0;
156 for ($self->{notebook}->pages) {
157 $_->set_dockbar_pos ($i++);
158 }
159 }
160
161 # Returns all Dockables of this Dockbar
162 sub dockables {
163 my ($self) = @_;
164 values %{$self->{docks}}
165 }
166
167 # Returns whether the dockable is currently docked. (and not
168 # a floating window).
169 sub is_docked {
170 my ($self, $dockable) = @_;
171 return not exists $self->{dock_windows}->{"$dockable"};
172 }
173
174 # switching to a page
175 sub user_switch_to_page {
176 my ($self, $page) = @_;
177 $page = $page eq '0' ? 10 : $page;
178
179 my @tabs = $self->{notebook}->pages;
180
181 for (my $i = 0; $i < ($page - 1); $i++) {
182 shift @tabs;
183 }
184
185 my $page = shift @tabs;
186 return unless $page;
187
188 $self->{notebook}->set_current_page ($page);
189 }
190
191 # This method activates the tab of the dockable if it is docked.
192 sub select_dockable {
193 my ($self, $dockable) = @_;
194 return unless exists $self->{docks}->{"$dockable"};
195 $self->{notebook}->set_current_page ($dockable);
196 }
197
198 # close current tab
199 sub close_current_tab {
200 my ($self) = @_;
201
202 if ($self->{notebook}->get_current_page) {
203 my $curdock = $self->{notebook}->get_current_page;
204 $curdock->close;
205 }
206 }
207
208 # "activates" the current page
209 sub activate_current {
210 my ($self) = @_;
211
212 if ($self->{notebook}->get_current_page) {
213 $self->{notebook}->get_current_page->activate
214 }
215 }
216
217 1