FifeGUI 0.3.0
A C++ GUI library designed for games.
dropdown.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later OR BSD-3-Clause
2// SPDX-FileCopyrightText: 2004 - 2008 Olof Naessén and Per Larsson
3// SPDX-FileCopyrightText: 2013 - 2026 Fifengine contributors
4
5// Corresponding header include
6#include "fifechan/widgets/dropdown.hpp"
7
8// Standard library includes
9#include <cassert>
10#include <memory>
11
12// Project headers (subdirs before local)
13#include "fifechan/exception.hpp"
14#include "fifechan/font.hpp"
15#include "fifechan/graphics.hpp"
16#include "fifechan/key.hpp"
17#include "fifechan/listmodel.hpp"
18#include "fifechan/mouseinput.hpp"
19#include "fifechan/widgets/listbox.hpp"
20#include "fifechan/widgets/scrollarea.hpp"
21
22namespace fcn
23{
24 DropDown::DropDown(ListModel* listModel, ScrollArea* scrollArea, ListBox* listBox) :
25 mInternalScrollArea(scrollArea == nullptr), mInternalListBox(listBox == nullptr)
26 {
27 setWidth(100);
28 setFocusable(true);
29
31 mOwnedScrollArea = std::make_unique<ScrollArea>();
33 } else {
34 mScrollArea = scrollArea;
35 }
36
37 if (mInternalListBox) {
38 mOwnedListBox = std::make_unique<ListBox>();
39 mListBox = mOwnedListBox.get();
40 } else {
41 mListBox = listBox;
42 }
43
44 assert("mScrollArea must not be null after construction" && mScrollArea != nullptr);
45 assert("mListBox must not be null after construction" && mListBox != nullptr);
46
47 mScrollArea->setContent(mListBox);
49
50 mListBox->addActionListener(this);
51 mListBox->addSelectionListener(this);
52
53 setListModel(listModel);
54
55 addMouseListener(this);
56 addKeyListener(this);
57 addFocusListener(this);
58
60 }
61
62 DropDown::~DropDown()
63 {
67 }
68
70 }
71
72 void DropDown::draw(Graphics* graphics)
73 {
74 assert("graphics must not be null" && graphics != nullptr);
75 assert("font must not be null" && getFont() != nullptr);
76
77 int h = 0;
78
79 if (mDroppedDown) {
81 } else {
82 h = getHeight();
83 }
84
85 Color const faceColor = getBaseColor();
86 Color highlightColor;
87 Color shadowColor;
88 int const alpha = getBaseColor().a;
89 highlightColor = faceColor + 0x303030;
90 highlightColor.a = alpha;
91 shadowColor = faceColor - 0x303030;
92 shadowColor.a = alpha;
93
94 // Draw a border.
95 graphics->setColor(shadowColor);
96 graphics->drawLine(0, 0, getWidth() - 1, 0);
97 graphics->drawLine(0, 1, 0, h - 2);
98 graphics->setColor(highlightColor);
99 graphics->drawLine(getWidth() - 1, 1, getWidth() - 1, h - 1);
100 graphics->drawLine(0, h - 1, getWidth() - 1, h - 1);
101
102 // Push a clip area so the other drawings don't need to worry
103 // about the border.
104 graphics->pushClipArea(Rectangle(1, 1, getWidth() - 2, h - 2));
105 ClipRectangle const & currentClipArea = graphics->getCurrentClipArea();
106
107 graphics->setColor(getBackgroundColor());
108 graphics->fillRectangle(0, 0, currentClipArea.width, currentClipArea.height);
109
110 if (isFocused()) {
111 graphics->setColor(getSelectionColor());
112 graphics->fillRectangle(0, 0, currentClipArea.width - currentClipArea.height, currentClipArea.height);
113 graphics->setColor(getForegroundColor());
114 }
115
116 if ((mListBox->getListModel() != nullptr) && mListBox->getSelected() >= 0) {
117 graphics->setColor(getForegroundColor());
118 graphics->setFont(getFont());
119
120 graphics->drawText(mListBox->getListModel()->getElementAt(mListBox->getSelected()), 1, 0);
121 } else if ((mListBox->getListModel() != nullptr) && mListBox->getSelected() < 0) {
122 graphics->setColor(getForegroundColor());
123 graphics->setFont(getFont());
124
125 graphics->drawText("", 1, 0);
126 }
127
128 // Push a clip area before drawing the button.
129 graphics->pushClipArea(Rectangle(
130 currentClipArea.width - currentClipArea.height, 0, currentClipArea.height, currentClipArea.height));
131 drawButton(graphics);
132 graphics->popClipArea();
133 graphics->popClipArea();
134
135 if (mDroppedDown) {
136 // Draw a border around the children.
137 graphics->setColor(shadowColor);
139 // drawChildren(graphics);
140 }
141 }
142
144 {
145 Color faceColor;
146 Color highlightColor;
147 Color shadowColor;
148 int offset = 0;
149 int const alpha = getBaseColor().a;
150
151 if (mPushed) {
152 faceColor = getBaseColor() - 0x303030;
153 faceColor.a = alpha;
154 highlightColor = faceColor - 0x303030;
155 highlightColor.a = alpha;
156 shadowColor = faceColor + 0x303030;
157 shadowColor.a = alpha;
158 offset = 1;
159 } else {
160 faceColor = getBaseColor();
161 faceColor.a = alpha;
162 highlightColor = faceColor + 0x303030;
163 highlightColor.a = alpha;
164 shadowColor = faceColor - 0x303030;
165 shadowColor.a = alpha;
166 offset = 0;
167 }
168
169 ClipRectangle const & currentClipArea = graphics->getCurrentClipArea();
170 graphics->setColor(highlightColor);
171 graphics->drawLine(0, 0, currentClipArea.width - 1, 0);
172 graphics->drawLine(0, 1, 0, currentClipArea.height - 1);
173 graphics->setColor(shadowColor);
174 graphics->drawLine(currentClipArea.width - 1, 1, currentClipArea.width - 1, currentClipArea.height - 1);
175 graphics->drawLine(1, currentClipArea.height - 1, currentClipArea.width - 2, currentClipArea.height - 1);
176
177 graphics->setColor(faceColor);
178 graphics->fillRectangle(1, 1, currentClipArea.width - 2, currentClipArea.height - 2);
179
180 graphics->setColor(getForegroundColor());
181
182 int i = 0;
183 int const n = currentClipArea.height / 3;
184 int const dx = currentClipArea.height / 2;
185 int const dy = (currentClipArea.height * 2) / 3;
186 for (i = 0; i < n; i++) {
187 graphics->drawLine(dx - i + offset, dy - i + offset, dx + i + offset, dy - i + offset);
188 }
189 }
190
192 {
193 return mListBox->getSelected();
194 }
195
196 void DropDown::setSelected(int selected)
197 {
198 mListBox->setSelected(selected);
199 }
200
202 {
203 if (keyEvent.isConsumed()) {
204 return;
205 }
206
207 Key const key = keyEvent.getKey();
208
209 if ((key.getValue() == fcn::Key::KEY_RETURN || key.getValue() == fcn::Key::SPACE) && !mDroppedDown) {
210 dropDown();
211 keyEvent.consume();
212 } else if (key.getValue() == fcn::Key::UP) {
214 keyEvent.consume();
215 } else if (key.getValue() == fcn::Key::DOWN) {
217 keyEvent.consume();
218 }
219 }
220
222 {
223 // If we have a mouse press on the widget.
224 if (mouseEvent.getButton() == MouseEvent::Button::Left && !mDroppedDown && isMouseInside(mouseEvent)) {
225 mPushed = true;
226 dropDown();
227 if (mFocusHandler != nullptr) {
228 mFocusHandler->pushModal(nullptr, this);
229 }
230 } else if (
231 // Fold up the listbox if the upper part is clicked after fold down
232 mouseEvent.getButton() == MouseEvent::Button::Left && mDroppedDown && isMouseInside(mouseEvent) &&
233 (mouseEvent.getY() < mFoldedUpHeight)) {
234 mPushed = false;
235 foldUp();
236 if (mFocusHandler != nullptr) {
237 mFocusHandler->popModal();
238 }
239 } else if (
240 // If we have a mouse press outside the widget
241 !isMouseInside(mouseEvent)) {
242 mPushed = false;
243 foldUp();
244 }
245 }
246
248 {
249 if (mIsDragged) {
250 mPushed = false;
251 }
252
253 // Released outside of widget. Can happen when we have modal input focus.
254 if (!isMouseInside(mouseEvent) && mouseEvent.getButton() == MouseEvent::Button::Left && isUnderMouseModal()) {
255 if (mFocusHandler != nullptr) {
256 mFocusHandler->popModal();
257 }
258
259 if (mIsDragged) {
260 foldUp();
261 }
262 } else if (mouseEvent.getButton() == MouseEvent::Button::Left) {
263 mPushed = false;
264 }
265
266 mIsDragged = false;
267 }
268
270 {
271 mIsDragged = true;
272
273 mouseEvent.consume();
274 }
275
277 {
278 mListBox->setListModel(listModel);
279
280 adjustHeight();
281 }
282
284 {
285 return mListBox->getListModel();
286 }
287
289 {
290 if (mScrollArea == nullptr) {
291 throwException("Scroll area has been deleted.");
292 }
293
294 if (mListBox == nullptr) {
295 throwException("List box has been deleted.");
296 }
297
298 int const listBoxHeight = mListBox->getHeight();
299
300 // We add 2 for the border
301 int const h2 = getFont()->getHeight() + 2;
302
303 setHeight(h2);
304
305 // The addition/subtraction of 2 compensates for the separation lines,
306 // which are separating the selected element view and the scroll area.
307
308 if (mDroppedDown && (getParent() != nullptr)) {
309 int const h = getParent()->getChildrenArea().height - getY();
310
311 if (listBoxHeight > h - h2 - 2) {
312 mScrollArea->setHeight(h - h2 - 2);
313 setHeight(h);
314 } else {
315 setHeight(listBoxHeight + h2 + 2);
316 mScrollArea->setHeight(listBoxHeight);
317 }
318 }
319
320 mScrollArea->setWidth(getWidth());
321 // Resize the ListBox to exactly fit the ScrollArea.
322 mListBox->setWidth(mScrollArea->getChildrenArea().width);
323 mScrollArea->setPosition(0, 0);
324 }
325
326 void DropDown::resizeToContent(bool recursion)
327 {
328 (void)recursion; // unused parameter
329
330 if (mScrollArea != nullptr) {
331 mScrollArea->resizeToContent();
332 }
333
334 // TODO this seems to be a redundant calculation, please check again
335 /*if (mListBox != nullptr) {
336 mScrollArea->resizeToContent();
337 }*/
338
339 adjustHeight();
340 }
341
343 {
344 adjustHeight();
345 }
346
348 {
349 if (!mDroppedDown) {
350 mDroppedDown = true;
352 adjustHeight();
353
354 if (getParent() != nullptr) {
355 getParent()->moveToTop(this);
356 }
357 }
358
359 mListBox->requestFocus();
360 }
361
363 {
364 if (mDroppedDown) {
365 mDroppedDown = false;
366 adjustHeight();
367 if (mFocusHandler != nullptr) {
368 mFocusHandler->releaseFocus(this);
369 }
370 }
371 }
372
373 void DropDown::focusLost([[maybe_unused]] Event const & event)
374 {
375 foldUp();
376 if (mFocusHandler != nullptr) {
377 mFocusHandler->releaseFocus(this);
378 }
379 }
380
381 void DropDown::death(Event const & event)
382 {
383 if (event.getSource() == mScrollArea) {
384 if (mOwnedScrollArea.get() == mScrollArea) {
385 [[maybe_unused]] auto* released = mOwnedScrollArea.release();
386 (void)released;
387 }
388 mScrollArea = nullptr;
389 }
390 }
391
392 void DropDown::action([[maybe_unused]] ActionEvent const & actionEvent)
393 {
394 foldUp();
395 if (mFocusHandler != nullptr) {
396 mFocusHandler->popModal();
397 }
399 }
400
402 {
403 if (mDroppedDown) {
404 // Calculate the children area (with the one pixel border in mind)
405 return {1, mFoldedUpHeight + 1, getWidth() - 2, getHeight() - mFoldedUpHeight - 2};
406 }
407
408 return {};
409 }
410
411 void DropDown::setBaseColor(Color const & color)
412 {
414 mScrollArea->setBaseColor(color);
415 }
416
417 if (mInternalListBox) {
418 mListBox->setBaseColor(color);
419 }
420
422 }
423
425 {
427 mScrollArea->setBackgroundColor(color);
428 }
429
430 if (mInternalListBox) {
431 mListBox->setBackgroundColor(color);
432 }
433
435 }
436
438 {
440 mScrollArea->setForegroundColor(color);
441 }
442
443 if (mInternalListBox) {
444 mListBox->setForegroundColor(color);
445 }
446
448 }
449
451 {
453 mScrollArea->setFont(font);
454 }
455
456 if (mInternalListBox) {
457 mListBox->setFont(font);
458 }
459
460 Widget::setFont(font);
461 }
462
464 {
465 if (isFocused() && isMouseInside(mouseEvent)) {
466 mouseEvent.consume();
467
468 if (mListBox->getSelected() > 0) {
469 mListBox->setSelected(mListBox->getSelected() - 1);
470 }
471 }
472 }
473
475 {
476 if (isFocused() && isMouseInside(mouseEvent)) {
477 mouseEvent.consume();
478
479 mListBox->setSelected(mListBox->getSelected() + 1);
480 }
481 }
482
484 {
486
487 if (mInternalListBox) {
488 mListBox->setSelectionColor(color);
489 }
490 }
491
492 void DropDown::valueChanged([[maybe_unused]] SelectionEvent const & event)
493 {
495 }
496
498 {
499 mSelectionListeners.push_back(selectionListener);
500 }
501
502 // cppcheck-suppress constParameterPointer
504 {
505 mSelectionListeners.remove(selectionListener);
506 }
507
509 {
511
512 for (iter = mSelectionListeners.begin(); iter != mSelectionListeners.end(); ++iter) {
513 SelectionEvent const event(this);
514 (*iter)->valueChanged(event);
515 }
516 }
517} // namespace fcn
Represents an action trigger (e.g., button click).
A rectangle specifically used for clipping rendering regions.
Color.
Definition color.hpp:58
uint8_t a
Alpha color component (0-255).
Definition color.hpp:350
void draw(Graphics *graphics) override
Draws the widget.
Definition dropdown.cpp:72
virtual void death(Event const &event)
DeathListener callback invoked when a observed widget is destroyed.
Definition dropdown.cpp:381
void setFont(Font *font) override
Set the font used to render items in the dropdown.
Definition dropdown.cpp:450
void action(ActionEvent const &actionEvent) override
Handles an action event emitted by a widget.
Definition dropdown.cpp:392
DropDown(ListModel *listModel=nullptr, ScrollArea *scrollArea=nullptr, ListBox *listBox=nullptr)
Constructor.
Definition dropdown.cpp:24
bool mInternalListBox
True if an internal list box is used, false if a list box has been passed to the drop down which the ...
Definition dropdown.hpp:270
bool mIsDragged
True if the drop down is dragged.
Definition dropdown.hpp:275
bool mInternalScrollArea
True if an internal scroll area is used, false if a scroll area has been passed to the drop down whic...
Definition dropdown.hpp:263
void focusLost(Event const &event) override
Called when a widget loses focus.
Definition dropdown.cpp:373
void adjustSize() override
Resizes the widget's size to fit the content exactly.
Definition dropdown.cpp:342
ScrollArea * mScrollArea
The scroll area used.
Definition dropdown.hpp:251
virtual void dropDown()
Sets the drop down to be dropped down.
Definition dropdown.cpp:347
void mouseWheelMovedDown(MouseEvent &mouseEvent) override
Called when the mouse wheel has moved down on the widget area.
Definition dropdown.cpp:474
std::unique_ptr< ScrollArea > mOwnedScrollArea
Owned internal scroll area when not supplied externally.
Definition dropdown.hpp:241
void mouseDragged(MouseEvent &mouseEvent) override
Called when the mouse has moved and the mouse has previously been pressed on the widget.
Definition dropdown.cpp:269
Rectangle getChildrenArea() override
Gets the area of the widget occupied by the widget's children.
Definition dropdown.cpp:401
void valueChanged(SelectionEvent const &event) override
Called when the value of a selection has been changed in a Widget.
Definition dropdown.cpp:492
void removeSelectionListener(SelectionListener *selectionListener)
Removes a selection listener from the drop down.
Definition dropdown.cpp:503
virtual void drawButton(Graphics *graphics)
Draws the button of the drop down.
Definition dropdown.cpp:143
SelectionListenerList mSelectionListeners
The selection listener's of the drop down.
Definition dropdown.hpp:283
int getSelected() const
Gets the selected item as an index in the list model.
Definition dropdown.cpp:191
void resizeToContent(bool recursion=true) override
Resizes the widget's size to fit the content exactly, calls recursively all childs.
Definition dropdown.cpp:326
ListBox * mListBox
The list box used.
Definition dropdown.hpp:256
void setListModel(ListModel *listModel)
Sets the list model to use when displaying the list.
Definition dropdown.cpp:276
void keyPressed(KeyEvent &keyEvent) override
Called if a key is pressed when the widget has keyboard focus.
Definition dropdown.cpp:201
void mouseReleased(MouseEvent &mouseEvent) override
Called when a mouse button has been released on the widget area.
Definition dropdown.cpp:247
void setForegroundColor(Color const &color) override
Set the foreground/text color used in the dropdown.
Definition dropdown.cpp:437
void adjustHeight()
Adjusts the height of the drop down to fit the height of the drop down's parent's height.
Definition dropdown.cpp:288
void setBackgroundColor(Color const &color) override
Set the explicit background color for the dropdown.
Definition dropdown.cpp:424
bool mDroppedDown
True if the drop down is dropped down, false otherwise.
Definition dropdown.hpp:223
bool mPushed
True if the drop down has been pushed with the mouse, false otherwise.
Definition dropdown.hpp:229
void setSelected(int selected)
Sets the selected item.
Definition dropdown.cpp:196
void setBaseColor(Color const &color) override
Set the base color used for the dropdown background/controls.
Definition dropdown.cpp:411
virtual void foldUp()
Sets the drop down to be folded up.
Definition dropdown.cpp:362
void setSelectionColor(Color const &color) override
Set the color used for the selected item highlight.
Definition dropdown.cpp:483
void addSelectionListener(SelectionListener *selectionListener)
Adds a selection listener to the drop down.
Definition dropdown.cpp:497
void distributeValueChangedEvent()
Distributes a value changed event to all selection listeners of the drop down.
Definition dropdown.cpp:508
ListModel * getListModel() const
Gets the list model used.
Definition dropdown.cpp:283
std::unique_ptr< ListBox > mOwnedListBox
Owned internal list box when not supplied externally.
Definition dropdown.hpp:246
void mousePressed(MouseEvent &mouseEvent) override
Called when a mouse button has been pressed down on the widget area.
Definition dropdown.cpp:221
SelectionListenerList::iterator SelectionListenerIterator
Iterator for SelectionListenerList.
Definition dropdown.hpp:286
int mFoldedUpHeight
Holds what the height is if the drop down is folded up.
Definition dropdown.hpp:236
void mouseWheelMovedUp(MouseEvent &mouseEvent) override
Called when the mouse wheel has moved up on the widget area.
Definition dropdown.cpp:463
Base class for all GUI event objects.
Definition event.hpp:25
Widget * getSource() const
Gets the source widget of the event.
Definition event.cpp:20
Abstract interface for font rendering.
Definition font.hpp:26
virtual int getHeight() const =0
Gets the height of the glyphs in the font.
Abstract interface providing primitive drawing functions (lines, rectangles, etc.).
Definition graphics.hpp:58
virtual void popClipArea()
Removes the top most clip area from the stack.
Definition graphics.cpp:65
void drawText(std::string const &text, int x, int y)
Draws text with a default left alignment.
Definition graphics.hpp:401
virtual ClipRectangle const & getCurrentClipArea()
Gets the current clip area.
Definition graphics.cpp:74
virtual bool pushClipArea(Rectangle area)
Pushes a clip area onto the stack.
Definition graphics.cpp:25
virtual void setFont(Font *font)
Sets the font to use when drawing text.
Definition graphics.cpp:91
virtual void drawLine(int x1, int y1, int x2, int y2)=0
Draws a line.
virtual void setColor(Color const &color)=0
Sets the color to use when drawing.
virtual void drawRectangle(Rectangle const &rectangle)=0
Draws a simple, non-filled rectangle with a one pixel width.
virtual void fillRectangle(Rectangle const &rectangle)=0
Draws a filled rectangle.
bool isConsumed() const
Checks if the input event is consumed.
void consume()
Marks this event as consumed.
Represents a key event.
Definition keyevent.hpp:26
Key const & getKey() const
Gets the key of the event.
Definition keyevent.cpp:48
A scrollable list box allowing item selection.
Definition listbox.hpp:38
void removeSelectionListener(SelectionListener *selectionListener)
Removes a selection listener from the list box.
Definition listbox.cpp:267
Interface for a data model representing a list (used by ListBox/DropDown).
Definition listmodel.hpp:26
Represents a mouse event.
int getY() const
Gets the y coordinate of the mouse event.
MouseEvent::Button getButton() const
Gets the button of the mouse event.
Represents a rectangular area (X, Y, Width, Height).
Definition rectangle.hpp:22
int width
Holds the width of the rectangle.
int height
Holds the height of the rectangle.
A scrollable viewport for viewing widgets larger than the visible area.
Represents a change in selection state (e.g., list item selected).
SelectionListener(SelectionListener const &)=default
Copy constructor.
void addFocusListener(FocusListener *focusListener)
Adds a focus listener to the widget.
Definition widget.cpp:896
Color const & getBaseColor() const
Gets the base color.
Definition widget.cpp:742
int getY() const
Gets the y coordinate of the widget.
Definition widget.cpp:301
void setFocusable(bool focusable)
Sets the widget to be focusable, or not.
Definition widget.cpp:646
bool isMouseInside(MouseEvent const &mouseEvent) const
Checks if a mouse event occurred within this widget.
Definition widget.cpp:275
FocusHandler * mFocusHandler
Holds the focus handler used by the widget.
Definition widget.hpp:1891
virtual bool isUnderMouseModal() const
Checks if the widget or its parent is under a mouse modal.
Definition widget.cpp:1115
int getWidth() const
Gets the width of the widget.
Definition widget.cpp:252
virtual Widget * getParent() const
Gets the widget's parent container.
Definition widget.cpp:239
void add(Widget *widget)
Adds a child to the widget.
Definition widget.cpp:1446
virtual Rectangle getChildrenArea()
Gets the area of the widget occupied by the widget's children.
Definition widget.cpp:1166
virtual void moveToTop(Widget *widget)
Moves a widget to the top of this widget.
Definition widget.cpp:1464
virtual bool isFocused() const
Checks if the widget is focused.
Definition widget.cpp:624
void removeActionListener(ActionListener *actionListener)
Removes an added action listener from the widget.
Definition widget.cpp:869
Color const & getBackgroundColor() const
Gets the background color.
Definition widget.cpp:762
virtual void setForegroundColor(Color const &color)
Sets the foreground color.
Definition widget.cpp:747
void addMouseListener(MouseListener *mouseListener)
Adds a mouse listener to the widget.
Definition widget.cpp:907
static bool widgetExists(Widget const *widget)
Checks if a widget exists or not, that is if it still exists an instance of the object.
Definition widget.cpp:1037
virtual void setWidth(int width)
Sets the width of the widget.
Definition widget.cpp:244
void addKeyListener(KeyListener *keyListener)
Adds a key listener to the widget.
Definition widget.cpp:885
void setInternalFocusHandler(FocusHandler *internalFocusHandler)
Sets the internal focus handler.
Definition widget.cpp:1176
virtual void setBaseColor(Color const &color)
Sets the base color of the widget.
Definition widget.cpp:737
Color const & getForegroundColor() const
Gets the foreground color.
Definition widget.cpp:752
virtual void setFont(Font *font)
Sets the font for the widget.
Definition widget.cpp:1031
Font * getFont() const
Gets the font set for the widget.
Definition widget.cpp:1000
void distributeActionEvent()
Distributes an action event to all action listeners of the widget.
Definition widget.cpp:1291
int getHeight() const
Gets the height of the widget.
Definition widget.cpp:265
virtual void setSelectionColor(Color const &color)
Sets the selection color.
Definition widget.cpp:767
virtual void setHeight(int height)
Sets the height of the widget.
Definition widget.cpp:257
Color const & getSelectionColor() const
Gets the selection color.
Definition widget.cpp:772
virtual void setBackgroundColor(Color const &color)
Sets the background color.
Definition widget.cpp:757
Used replacement tokens by configure_file():
void throwException(std::string const &message, std::source_location location=std::source_location::current())
Throw an Exception capturing the current source location.