Update list of wide characters
[centerim5.git] / cppconsui / SplitDialog.cpp
blobdc0bc1e0a1b49ffb5683f2e254b528535ffb060e
1 // Copyright (C) 2010-2015 Petr Pavlu <setup@dagobah.cz>
2 //
3 // This file is part of CenterIM.
4 //
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.
9 //
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/>.
18 /// @file
19 /// SplitDialog class implementation.
20 ///
21 /// @ingroup cppconsui
23 #include "SplitDialog.h"
25 #include <cassert>
27 namespace CppConsUI {
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
46 // too late.
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();
56 if (f != nullptr) {
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);
80 return;
83 /// @todo Rewrite to take advantage of focus chain caching.
85 switch (direction) {
86 case FOCUS_PREVIOUS:
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())
94 return;
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())
105 return;
108 break;
109 case FOCUS_NEXT:
110 if (layout_->getFocusChild() == container_) {
111 // Focus is held by the container, give it to the first button.
112 if (buttons_->grabFocus())
113 return;
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())
124 return;
127 break;
128 case FOCUS_LEFT:
129 case FOCUS_RIGHT:
130 if (layout_->getFocusChild() != buttons_) {
131 // First try to focus the previously focused widget, if it fails then try
132 // any widget.
133 if ((buttons_old_focus_ && buttons_old_focus_->grabFocus()) ||
134 buttons_->grabFocus())
135 return;
137 break;
138 case FOCUS_UP:
139 case FOCUS_DOWN:
140 if (layout_->getFocusChild() != container_) {
141 // First try to focus the previously focused widget, if it fails then try
142 // any widget.
143 if ((cont_old_focus_ && cont_old_focus_->grabFocus()) ||
144 container_->grabFocus())
145 return;
147 break;
148 default:
149 break;
151 AbstractDialog::moveFocus(direction);
154 void SplitDialog::setContainer(Container &cont)
156 assert(container_ == nullptr);
158 container_ = &cont;
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)
170 if (visible)
171 return;
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;
181 else
182 assert(0);
185 } // namespace CppConsUI
187 // vim: set tabstop=2 shiftwidth=2 textwidth=80 expandtab: