1 /** @file libshell/src/inputdialog.cpp  Dialog for querying text from the user.
2  *
3  * @authors Copyright © 2013-2017 Jaakko Keränen <jaakko.keranen@iki.fi>
4  *
5  * @par License
6  * LGPL: http://www.gnu.org/licenses/lgpl.html
7  *
8  * <small>This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or (at your
11  * option) any later version. This program is distributed in the hope that it
12  * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
14  * General Public License for more details. You should have received a copy of
15  * the GNU Lesser General Public License along with this program; if not, see:
16  * http://www.gnu.org/licenses</small>
17  */
18 
19 #include "de/shell/InputDialog"
20 #include "de/shell/LabelWidget"
21 #include "de/shell/LineEditWidget"
22 #include "de/shell/MenuWidget"
23 #include "de/shell/TextRootWidget"
24 
25 namespace de { namespace shell {
26 
DENG2_PIMPL_NOREF(InputDialog)27 DENG2_PIMPL_NOREF(InputDialog)
28 {
29     LabelWidget *   label;
30     LineEditWidget *edit;
31     MenuWidget *    menu;
32     String          userText;
33     int             result;
34 
35     Impl() : label(0), edit(0), menu(0), result(0)
36     {}
37 
38     ~Impl()
39     {}
40 };
41 
InputDialog(String const & name)42 InputDialog::InputDialog(String const &name)
43     : DialogWidget(name), d(new Impl)
44 {
45     RuleRectangle &rect = rule();
46 
47     // Label.
48     d->label = new LabelWidget;
49     d->label->setExpandsToFitLines(true); // determines height independently
50 
51     d->label->rule()
52             .setInput(Rule::Width, rect.width())
53             .setInput(Rule::Top,   rect.top())
54             .setInput(Rule::Left,  rect.left());
55 
56     // Address editor.
57     d->edit = new LineEditWidget;
58     d->edit->setName(d->edit->uniqueName("edit"));
59 
60     d->edit->rule()
61             .setInput(Rule::Width, rect.width())
62             .setInput(Rule::Left,  rect.left())
63             .setInput(Rule::Top,   d->label->rule().bottom() + 1);
64 
65     // Menu for actions.
66     d->menu = new MenuWidget(MenuWidget::AlwaysOpen);
67     d->menu->setName(d->menu->uniqueName("menu"));
68     d->menu->setBorder(MenuWidget::NoBorder);
69     d->menu->setBackgroundAttribs(TextCanvas::Char::DefaultAttributes);
70     d->menu->setSelectionAttribs(TextCanvas::Char::Reverse);
71     d->menu->appendItem(new Action(tr("OK"), this, SLOT(accept())));
72     d->menu->appendItem(new Action(tr("Cancel"), KeyEvent(Qt::Key_C, KeyEvent::Control),
73                                    this, SLOT(reject())), "Ctrl-C");
74 
75     d->menu->rule()
76             .setInput(Rule::Width,  rect.width())
77             .setInput(Rule::Left,   rect.left())
78             .setInput(Rule::Bottom, rect.bottom());
79 
80     add(d->label);
81     add(d->edit);
82     add(d->menu);
83 
84     setFocusCycle(WidgetList() << d->edit << d->menu);
85 
86     // Outer dimensions.
87     rect.setInput(Rule::Width, Const(50));
88     rect.setInput(Rule::Height,
89                   d->menu->rule().height() +
90                   d->edit->rule().height() +
91                   d->label->rule().height() + 2);
92 }
93 
label()94 LabelWidget &InputDialog::label()
95 {
96     return *d->label;
97 }
98 
lineEdit()99 LineEditWidget &InputDialog::lineEdit()
100 {
101     return *d->edit;
102 }
103 
menu()104 MenuWidget &InputDialog::menu()
105 {
106     return *d->menu;
107 }
108 
setWidth(int width)109 void InputDialog::setWidth(int width)
110 {
111     rule().setInput(Rule::Width, Const(width));
112 }
113 
setDescription(String const & desc)114 void InputDialog::setDescription(String const &desc)
115 {
116     d->label->setLabel(desc);
117 }
118 
setPrompt(String const & prompt)119 void InputDialog::setPrompt(String const &prompt)
120 {
121     d->edit->setPrompt(prompt);
122 }
123 
setText(String const & text)124 void InputDialog::setText(String const &text)
125 {
126     d->edit->setText(text);
127 }
128 
setAcceptLabel(String const & label)129 void InputDialog::setAcceptLabel(String const &label)
130 {
131     d->menu->itemAction(0).setLabel(label);
132     redraw();
133 }
134 
setRejectLabel(String const & label)135 void InputDialog::setRejectLabel(String const &label)
136 {
137     d->menu->itemAction(1).setLabel(label);
138     redraw();
139 }
140 
prepare()141 void InputDialog::prepare()
142 {
143     DialogWidget::prepare();
144 
145     d->userText.clear();
146     d->result = 0;
147 
148     root().setFocus(d->edit);
149 }
150 
finish(int result)151 void InputDialog::finish(int result)
152 {
153     d->result = result;
154     d->userText.clear();
155     if (result) d->userText = d->edit->text();
156 
157     DialogWidget::finish(result);
158 }
159 
text() const160 String InputDialog::text() const
161 {
162     return d->userText;
163 }
164 
result() const165 int InputDialog::result() const
166 {
167     return d->result;
168 }
169 
170 }} // namespace de::shell
171