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