Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2006-2024 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file MFXTextFieldSearch.cpp
15 : /// @author Pablo Alvarez Lopez
16 : /// @date May 2023
17 : ///
18 : // TextField for search elements
19 : /****************************************************************************/
20 :
21 : #include <utils/common/MsgHandler.h>
22 : #include <utils/gui/windows/GUIAppEnum.h>
23 : #include <utils/gui/images/GUIIconSubSys.h>
24 :
25 : #include "MFXTextFieldSearch.h"
26 :
27 : // =========================================================================
28 : // defines
29 : // =========================================================================
30 :
31 : #define ICON_SPACING 4 // Spacing between icon and label (2 + 2)
32 : #define ICON_SIZE 16
33 :
34 : // ===========================================================================
35 : // FOX callback mapping
36 : // ===========================================================================
37 :
38 : FXDEFMAP(MFXTextFieldSearch) MFXTextFieldSearchMap[] = {
39 : FXMAPFUNC(SEL_PAINT, 0, MFXTextFieldSearch::onPaint),
40 : FXMAPFUNC(SEL_FOCUSIN, 0, MFXTextFieldSearch::onFocusIn),
41 : FXMAPFUNC(SEL_FOCUSOUT, 0, MFXTextFieldSearch::onFocusOut),
42 : FXMAPFUNC(SEL_FOCUS_SELF, 0, MFXTextFieldSearch::onFocusSelf),
43 : FXMAPFUNC(SEL_KEYPRESS, 0, MFXTextFieldSearch::onKeyPress),
44 : };
45 :
46 : // Object implementation
47 0 : FXIMPLEMENT(MFXTextFieldSearch, MFXTextFieldIcon, MFXTextFieldSearchMap, ARRAYNUMBER(MFXTextFieldSearchMap))
48 :
49 : // ===========================================================================
50 : // member method definitions
51 : // ===========================================================================
52 :
53 0 : MFXTextFieldSearch::MFXTextFieldSearch(FXComposite* p, FXint ncols, FXObject* tgt, FXSelector sel, FXuint opt, FXint x, FXint y, FXint w, FXint h, FXint pl, FXint pr, FXint pt, FXint pb) :
54 : MFXTextFieldIcon(p, ncols, GUIIconSubSys::getIcon(GUIIcon::SEARCH), tgt, sel, opt, x, y, w, h, pl, pr, pt, pb),
55 0 : myTarget(tgt) {
56 0 : }
57 :
58 :
59 : long
60 0 : MFXTextFieldSearch::onKeyPress(FXObject* obj, FXSelector sel, void* ptr) {
61 0 : MFXTextFieldIcon::onKeyPress(obj, sel, ptr);
62 0 : return myTarget->handle(this, FXSEL(SEL_COMMAND, MID_MTEXTFIELDSEARCH_UPDATED), ptr);
63 : }
64 :
65 :
66 : long
67 0 : MFXTextFieldSearch::onPaint(FXObject*, FXSelector, void* ptr) {
68 : FXEvent* ev = (FXEvent*)ptr;
69 0 : FXDCWindow dc(this, ev);
70 : // Draw frame
71 0 : drawFrame(dc, 0, 0, width, height);
72 : // Gray background if disabled
73 0 : if (isEnabled()) {
74 0 : dc.setForeground(backColor);
75 : } else {
76 0 : dc.setForeground(baseColor);
77 : }
78 : // Draw background
79 0 : dc.fillRectangle(border, border, width - (border << 1), height - (border << 1));
80 : // Draw text, clipped against frame interior
81 0 : dc.setClipRectangle(border, border, width - (border << 1), height - (border << 1));
82 : // continue depending of search string
83 0 : if (hasFocus() || (contents.count() > 0)) {
84 0 : drawTextRange(dc, 0, contents.length());
85 : } else {
86 0 : drawSearchTextRange(dc, 0, TL("Type to search..."));
87 : }
88 : // Draw caret
89 0 : if (flags & FLAG_CARET) {
90 0 : int xx = coord(cursor) - 1;
91 0 : xx += ICON_SPACING + ICON_SIZE;
92 0 : dc.setForeground(cursorColor);
93 0 : dc.fillRectangle(xx, padtop + border, 1, height - padbottom - padtop - (border << 1));
94 0 : dc.fillRectangle(xx - 2, padtop + border, 5, 1);
95 0 : dc.fillRectangle(xx - 2, height - border - padbottom - 1, 5, 1);
96 : }
97 : // draw icon
98 0 : dc.drawIcon(icon, 3, border + padtop + (height - padbottom - padtop - (border << 1) - ICON_SIZE) / 2);
99 0 : return 1;
100 0 : }
101 :
102 :
103 : long
104 0 : MFXTextFieldSearch::onFocusIn(FXObject* sender, FXSelector sel, void* ptr) {
105 0 : update();
106 0 : return MFXTextFieldIcon::onFocusIn(sender, sel, ptr);
107 : }
108 :
109 :
110 :
111 : long
112 0 : MFXTextFieldSearch::onFocusOut(FXObject* sender, FXSelector sel, void* ptr) {
113 0 : update();
114 0 : return MFXTextFieldIcon::onFocusOut(sender, sel, ptr);
115 : }
116 :
117 :
118 :
119 : long
120 0 : MFXTextFieldSearch::onFocusSelf(FXObject* sender, FXSelector sel, void* ptr) {
121 : //onPaint(sender, sel, ptr);
122 0 : return MFXTextFieldIcon::onFocusSelf(sender, sel, ptr);
123 : }
124 :
125 :
126 0 : MFXTextFieldSearch::MFXTextFieldSearch() :
127 0 : MFXTextFieldIcon() {
128 0 : }
129 :
130 :
131 : void
132 0 : MFXTextFieldSearch::drawSearchTextRange(FXDCWindow& dc, FXint fm, const FXString& searchString) {
133 : FXint xx, yy, cw, hh, ww, si, ei, lx, rx, t;
134 0 : FXint rr = width - border - padright;
135 0 : FXint ll = border + padleft;
136 0 : FXint mm = (ll + rr) / 2;
137 : FXint to = (int)searchString.length();
138 0 : if (to <= fm) {
139 : return;
140 : }
141 0 : dc.setFont(font);
142 : // Text color
143 0 : dc.setForeground(FXRGBA(128, 128, 128, 255));
144 : // Height
145 0 : hh = font->getFontHeight();
146 : // Text sticks to top of field
147 0 : if (options & JUSTIFY_TOP) {
148 0 : yy = padtop + border;
149 0 : } else if (options & JUSTIFY_BOTTOM) {
150 : // Text sticks to bottom of field
151 0 : yy = height - padbottom - border - hh;
152 : } else {
153 : // Text centered in y
154 0 : yy = border + padtop + (height - padbottom - padtop - (border << 1) - hh) / 2;
155 : }
156 : if (anchor < cursor) {
157 : si = anchor;
158 : ei = cursor;
159 : } else {
160 : si = cursor;
161 : ei = anchor;
162 : }
163 : // Normal mode
164 0 : ww = font->getTextWidth(searchString.text(), searchString.length());
165 : // Text sticks to right of field
166 0 : if (options & JUSTIFY_RIGHT) {
167 0 : xx = shift + rr - ww;
168 0 : } else if (options & JUSTIFY_LEFT) {
169 : // Text sticks on left of field
170 0 : xx = shift + ll;
171 : } else {
172 : // Text centered in field
173 0 : xx = shift + mm - ww / 2;
174 : }
175 : // add icon spacing
176 0 : xx += ICON_SPACING + ICON_SIZE;
177 : // Reduce to avoid drawing excessive amounts of text
178 0 : lx = xx + font->getTextWidth(&searchString[0], fm);
179 0 : rx = lx + font->getTextWidth(&searchString[fm], to - fm);
180 0 : while (fm < to) {
181 0 : t = searchString.inc(fm);
182 0 : cw = font->getTextWidth(&searchString[fm], t - fm);
183 0 : if (lx + cw >= 0) {
184 : break;
185 : }
186 : lx += cw;
187 : fm = t;
188 : }
189 0 : while (fm < to) {
190 0 : t = searchString.dec(to);
191 0 : cw = font->getTextWidth(&searchString[t], to - t);
192 0 : if (rx - cw < width) {
193 : break;
194 : }
195 : rx -= cw;
196 : to = t;
197 : }
198 : // Adjust selected range
199 : if (si < fm) {
200 : si = fm;
201 : }
202 : if (ei > to) {
203 : ei = to;
204 : }
205 : // draw text
206 0 : xx += font->getTextWidth(searchString.text(), fm);
207 0 : yy += font->getFontAscent();
208 0 : dc.drawText(xx, yy, &searchString[fm], to - fm);
209 : }
|