1 // Copyright (C) 2010-2015 Petr Pavlu <setup@dagobah.cz>
3 // This file is part of CenterIM.
5 // CenterIM is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
10 // CenterIM is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with CenterIM. If not, see <http://www.gnu.org/licenses/>.
19 /// SplitDialog class implementation.
21 /// @ingroup cppconsui
23 #include "SplitDialog.h"
29 SplitDialog::SplitDialog(int x
, int y
, int w
, int h
, const char *title
)
30 : AbstractDialog(x
, y
, w
, h
, title
), container_(nullptr),
31 cont_old_focus_(nullptr), buttons_old_focus_(nullptr)
33 buttons_
->setFocusCycle(Container::FOCUS_CYCLE_LOCAL
);
36 SplitDialog::SplitDialog(const char *title
)
37 : AbstractDialog(title
), container_(nullptr), cont_old_focus_(nullptr),
38 buttons_old_focus_(nullptr)
40 buttons_
->setFocusCycle(Container::FOCUS_CYCLE_LOCAL
);
43 SplitDialog::~SplitDialog()
45 // Slots has to be disconnected manually because sigc::~trackable() is called
47 cont_old_focus_conn_
.disconnect();
48 cont_old_focus_
= nullptr;
49 buttons_old_focus_conn_
.disconnect();
50 buttons_old_focus_
= nullptr;
53 void SplitDialog::cleanFocus()
55 Widget
*f
= layout_
->getFocusChild();
57 if (f
== container_
) {
58 cont_old_focus_conn_
.disconnect();
59 cont_old_focus_
= container_
->getFocusWidget();
60 if (cont_old_focus_
!= nullptr)
61 cont_old_focus_conn_
= cont_old_focus_
->signal_visible
.connect(
62 sigc::mem_fun(this, &SplitDialog::onOldFocusVisible
));
64 else if (f
== buttons_
) {
65 buttons_old_focus_conn_
.disconnect();
66 buttons_old_focus_
= buttons_
->getFocusWidget();
67 if (buttons_old_focus_
!= nullptr)
68 buttons_old_focus_conn_
= buttons_old_focus_
->signal_visible
.connect(
69 sigc::mem_fun(this, &SplitDialog::onOldFocusVisible
));
73 AbstractDialog::cleanFocus();
76 void SplitDialog::moveFocus(FocusDirection direction
)
78 if (container_
== nullptr) {
79 AbstractDialog::moveFocus(direction
);
83 /// @todo Rewrite to take advantage of focus chain caching.
87 if (layout_
->getFocusChild() == container_
) {
88 // Focus is held by the container, give it to the last button.
89 FocusChain
focus_chain(nullptr);
90 buttons_
->getFocusChain(focus_chain
, focus_chain
.begin());
92 FocusChain::pre_order_iterator iter
= --focus_chain
.end();
93 if (*iter
!= nullptr && (*iter
)->grabFocus())
96 else if (layout_
->getFocusChild() == buttons_
) {
97 FocusChain
focus_chain(nullptr);
98 buttons_
->getFocusChain(focus_chain
, focus_chain
.begin());
100 FocusChain::leaf_iterator iter
= focus_chain
.begin_leaf();
101 if (getFocusWidget() == *iter
) {
102 // focus is held by the first button, give it to the container
103 if ((cont_old_focus_
&& cont_old_focus_
->grabFocus()) ||
104 container_
->grabFocus())
110 if (layout_
->getFocusChild() == container_
) {
111 // Focus is held by the container, give it to the first button.
112 if (buttons_
->grabFocus())
115 else if (layout_
->getFocusChild() == buttons_
) {
116 FocusChain
focus_chain(nullptr);
117 buttons_
->getFocusChain(focus_chain
, focus_chain
.begin());
119 FocusChain::pre_order_iterator iter
= --focus_chain
.end();
120 if (getFocusWidget() == *iter
) {
121 // Focus is held by the last button, give it to the container.
122 if ((cont_old_focus_
&& cont_old_focus_
->grabFocus()) ||
123 container_
->grabFocus())
130 if (layout_
->getFocusChild() != buttons_
) {
131 // First try to focus the previously focused widget, if it fails then try
133 if ((buttons_old_focus_
&& buttons_old_focus_
->grabFocus()) ||
134 buttons_
->grabFocus())
140 if (layout_
->getFocusChild() != container_
) {
141 // First try to focus the previously focused widget, if it fails then try
143 if ((cont_old_focus_
&& cont_old_focus_
->grabFocus()) ||
144 container_
->grabFocus())
151 AbstractDialog::moveFocus(direction
);
154 void SplitDialog::setContainer(Container
&cont
)
156 assert(container_
== nullptr);
159 cont
.setFocusCycle(Container::FOCUS_CYCLE_LOCAL
);
160 layout_
->insertWidget(0, cont
);
163 void SplitDialog::emitResponse(SplitDialog::ResponseType response
)
165 signal_response(*this, response
);
168 void SplitDialog::onOldFocusVisible(Widget
&activator
, bool visible
)
173 if (&activator
== cont_old_focus_
) {
174 cont_old_focus_conn_
.disconnect();
175 cont_old_focus_
= nullptr;
177 else if (&activator
== buttons_old_focus_
) {
178 buttons_old_focus_conn_
.disconnect();
179 buttons_old_focus_
= nullptr;
185 } // namespace CppConsUI
187 // vim: set tabstop=2 shiftwidth=2 textwidth=80 expandtab: