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