]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/DropDown.C
I fixed the two bugs (Very shallow in fact)
[lyx.git] / src / frontends / xforms / DropDown.C
1 /**
2  * \file DropDown.C
3  * Copyright 2001 the LyX Team
4  * Read the file COPYING
5  *
6  * \author John Levon, moz@compsoc.man.ac.uk
7  */
8
9 #include <config.h>
10
11 #ifdef __GNUG__
12 #pragma implementation
13 #endif
14
15 #include "DropDown.h"
16 #include "xforms_helpers.h"
17
18 #include FORMS_H_LOCATION
19
20 #include <iostream>
21 #include <cctype>
22
23 #ifndef CXX_GLOBAL_CSTD
24 using std::isprint;
25 #endif
26
27 using std::vector;
28
29
30 namespace {
31
32 extern "C" void C_CompletedCB(FL_OBJECT * ob, long)
33 {
34         DropDown * d = static_cast<DropDown*>(ob->u_vdata);
35         d->completed();
36 }
37
38
39 extern "C" int C_PeekCB(FL_FORM * form, void *xev)
40 {
41         DropDown * d = static_cast<DropDown*>(form->u_vdata);
42         return d->peek(static_cast<XEvent*>(xev));
43 }
44
45 } // namespace anon
46
47
48 DropDown::DropDown(FL_OBJECT * ob)
49 {
50         form_ = fl_bgn_form(FL_NO_BOX, ob->w, 100);
51         fl_add_box(FL_UP_BOX, 0, 0, ob->w, 100, "");
52         browser_ = fl_add_browser(FL_SELECT_BROWSER, 0, 0, ob->w, 100, "");
53         form_->u_vdata = this;
54         browser_->u_vdata = this;
55         fl_set_object_callback(browser_, C_CompletedCB, 0);
56         fl_register_raw_callback(form_, KeyPressMask|ButtonPressMask, C_PeekCB);
57         fl_end_form();
58 }
59
60
61 DropDown::~DropDown()
62 {
63         if (form_->visible)
64                 fl_hide_form(form_);
65         fl_free_form(form_);
66 }
67
68
69 void DropDown::select(vector<string> const & choices, int x, int y, int w)
70 {
71         if (choices.empty())
72                 return;
73
74         fl_set_form_geometry(form_, x, y-100, w, 100);
75         fl_clear_browser(browser_);
76
77         vector<string>::const_iterator cit = choices.begin();
78         vector<string>::const_iterator end = choices.end();
79         for (; cit != end; ++cit) {
80                 fl_add_browser_line(browser_, cit->c_str());
81         }
82         fl_select_browser_line(browser_, 1);
83         fl_show_form(form_, FL_PLACE_POSITION, FL_NOBORDER, "");
84         XGrabPointer(fl_get_display(), form_->window, false,
85                      ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
86                      GrabModeAsync, GrabModeAsync, 0, 0, 0);
87         XFlush(fl_get_display());
88 }
89
90
91 void DropDown::line_up()
92 {
93         if (fl_get_browser(browser_) > 1)
94                 fl_select_browser_line(browser_, fl_get_browser(browser_) - 1);
95         if (fl_get_browser(browser_) >= fl_get_browser_topline(browser_) +
96             fl_get_browser_screenlines(browser_))
97                 fl_set_browser_topline(browser_, fl_get_browser(browser_)
98                                        - fl_get_browser_screenlines(browser_) + 1);
99         if (fl_get_browser(browser_) < fl_get_browser_topline(browser_))
100                 fl_set_browser_topline(browser_, fl_get_browser(browser_));
101 }
102
103
104 void DropDown::line_down()
105 {
106         if (fl_get_browser(browser_) < fl_get_browser_maxline(browser_))
107                 fl_select_browser_line(browser_, fl_get_browser(browser_) + 1);
108         if (fl_get_browser(browser_) >= fl_get_browser_topline(browser_) +
109             fl_get_browser_screenlines(browser_))
110                 fl_set_browser_topline(browser_, fl_get_browser(browser_)
111                                        - fl_get_browser_screenlines(browser_) + 1);
112         if (fl_get_browser(browser_) < fl_get_browser_topline(browser_))
113                 fl_set_browser_topline(browser_, fl_get_browser(browser_));
114 }
115
116
117 int DropDown::peek(XEvent * xev)
118 {
119         int x,y;
120         unsigned int keymask;
121
122         fl_get_mouse(&x, &y, &keymask);
123
124         if (xev->type == ButtonPress) {
125                 if (!(x >= form_->x && x <= (form_->x + form_->w) &&
126                       y >= form_->y && y << (form_->y + form_->h))) {
127                         fl_hide_form(form_);
128                         return 1;
129                 }
130                 XUngrabPointer(fl_get_display(), CurrentTime);
131         } else if (xev->type == KeyPress) {
132                 char s_r[10]; s_r[9] = '\0';
133                 KeySym keysym_return;
134                 XLookupString(&xev->xkey, s_r, 10, &keysym_return, 0);
135                 switch (keysym_return) {
136                 case XK_Down:
137 #ifdef XK_KP_Down
138                 case XK_KP_Down:
139 #endif
140                         line_down();
141                         return 1;
142                 case XK_Up:
143 #ifdef XK_KP_Up
144                 case XK_KP_Up:
145 #endif
146                         line_up();
147                         return 1;
148                 case XK_Return:
149 #ifdef XK_KP_Enter
150                 case XK_KP_Enter:
151 #endif
152                         completed();
153                         return 1;
154                 case XK_Escape:
155                         fl_deselect_browser(browser_);
156                         completed();
157                         return 1;
158                 default:
159                         // FIXME: if someone has a got a way to
160                         // convince the event to fall back to the
161                         // minibuffer, I'm glad to hear it.
162                         // fl_XPutBackEvent() doesn't work.
163
164                         // This is a bit less elegant perhaps, but works
165                         // well enough. Angus 11 Jan 2002
166                         if (s_r[0] && isprint(s_r[0])) {
167                                 key_pressed(s_r[0]);
168                                 return 1;
169                         }
170                 }
171         }
172         return 0;
173 }
174
175
176 void DropDown::completed()
177 {
178         XUngrabPointer(fl_get_display(), CurrentTime);
179         fl_hide_form(form_);
180         result(getSelectedStringFromBrowser(browser_));
181 }
182
183
184 void DropDown::key_pressed(char c)
185 {
186         XUngrabPointer(fl_get_display(), CurrentTime);
187         fl_hide_form(form_);
188         keypress(c);
189 }