SavvyUI - C++ Component Library

A powerful C++ component library for the development of Windows Desktop Applications

Feature-rich, advanced, flexible, and easy-to-use!

SavvyUI C++ Components SavvyUI C++ Components SavvyUI C++ Components

Terms of use: You are free to use this library at no cost while developing your Windows application. However, a valid license is required before the application is released. This applies to all types of deployments, including commercial products and internal use within your organization. Please ensure that all released applications are properly licensed, as this policy is strictly enforced.


SavvyUI is a feature-rich windows c++ component library for the development of Windows Desktop applicatons. It features a large set of basic and advanced built-in components that can be used to create complex UI applications using C++. All the components have a familiar look and feel, and they are exceptionally easy to use. The library comes with built-in and customizable theme.




Components showcase



Accordion

An **accordion component** is a vertically stacked list of items that allows users to toggle the visibility of sections of related content. Each item typically consists of a header that can be clicked to expand or collapse its associated content panel. This interaction pattern helps streamline user interfaces by conserving screen space and organizing information into manageable, collapsible sections. Accordions are commonly used in FAQs, settings panels, and navigation menus to improve user experience by reducing visual clutter and allowing users to focus on specific sections without being overwhelmed by all the content at once. They can be customized with animations, icons, and responsive behavior to enhance usability and accessibility across devices.

Accordion Component
		class AccordionDemo : public GridPanel
		{
			Accordion _accordion;

			ButtonDemo _buttonDemo;
			ButtonGridDemo _buttonGridDemo;
			ButtonMenuDemo _buttonMenuDemo;
			TreeViewDemo _treeViewDemo;

		public:

			AccordionDemo()
			{
				_accordion.addPanel(L"Buttons", &_buttonDemo);
				_accordion.addPanel(L"Button Grid", &_buttonGridDemo);
				_accordion.addPanel(L"Button Menu", &_buttonMenuDemo);
				_accordion.addPanel(L"Tree View", &_treeViewDemo);

				setMargin(0);
				setLayout({ -1 }, { -1 });
				addComponent(&_accordion, 0, 0);
			}
			~AccordionDemo() {}
		};
										



Button Component

A **button component** is a fundamental interactive element in user interfaces, designed to trigger an action or event when clicked or tapped. Typically styled to stand out visually, a button can include text, icons, or both to clearly indicate its purpose—such as submitting a form, opening a dialog, navigating to another page, or executing a function. Button components can vary in size, color, shape, and state (e.g., active, disabled, loading) to convey hierarchy and interactivity. They are essential for guiding user interactions, and when implemented with accessibility in mind, they ensure a responsive and inclusive user experience across all devices and input methods.

Button Component
		class ButtonDemo : public FluidPanel, public ActionListener
		{
			Button _buttonDefault;
			Button _buttonPrimary;
			Button _buttonInfo;
			Button _buttonDanger;
			Button _buttonSuccess;
			Button _buttonWarn;

			Button _buttonGray;
			Button _buttonLightGray;
			Button _buttonBlue;
			Button _buttonLightBlue;
			Button _buttonTeal;
			Button _buttonCyan;
			Button _buttonPink;
			Button _buttonIndigo;
			Button _buttonOrange;
			Button _buttonBrown;
			Button _buttonSilver;
			Button _buttonRed;

		public:

			ButtonDemo()
			{
				_buttonDefault.setButtonType(ButtonType::DEFAULT);
				_buttonDefault.setText(L"DEFAULT");
				_buttonDefault.setImage(IconSource(L"deliveryorder.gif"));
				_buttonDefault.addActionListener(this);
				_buttonPrimary.setButtonType(ButtonType::PRIMARY);
				_buttonPrimary.setText(L"PRIMARY");
				_buttonPrimary.setImage(IconSource(IconType::ADD));
				_buttonPrimary.addActionListener(this);
				_buttonInfo.setButtonType(ButtonType::INFO);
				_buttonInfo.setText(L"INFO");
				_buttonInfo.addActionListener(this);
				_buttonDanger.setButtonType(ButtonType::DANGER);
				_buttonDanger.setText(L"DANGER");
				_buttonDanger.setImage(IconSource(IconType::REMOVE));
				_buttonDanger.addActionListener(this);
				_buttonSuccess.setButtonType(ButtonType::SUCCESS);
				_buttonSuccess.setText(L"SUCCESS");
				_buttonSuccess.addActionListener(this);
				_buttonWarn.setButtonType(ButtonType::WARN);
				_buttonWarn.setText(L"WARN");
				_buttonWarn.addActionListener(this);

				_buttonGray.setButtonType(ButtonType::GRAY);
				_buttonGray.setText(L"GRAY");
				_buttonGray.addActionListener(this);
				_buttonLightGray.setButtonType(ButtonType::LIGHTGRAY);
				_buttonLightGray.setText(L"LIGHTGRAY");
				_buttonLightGray.addActionListener(this);
				_buttonBlue.setButtonType(ButtonType::BLUE);
				_buttonBlue.setText(L"BLUE");
				_buttonBlue.addActionListener(this);
				_buttonLightBlue.setButtonType(ButtonType::LIGHTBLUE);
				_buttonLightBlue.setText(L"LIGHTBLUE");
				_buttonLightBlue.addActionListener(this);
				_buttonTeal.setButtonType(ButtonType::TEAL);
				_buttonTeal.setText(L"TEAL");
				_buttonTeal.addActionListener(this);
				_buttonCyan.setButtonType(ButtonType::CYAN);
				_buttonCyan.setText(L"CYAN");
				_buttonCyan.addActionListener(this);
				_buttonPink.setButtonType(ButtonType::PINK);
				_buttonPink.setText(L"PINK");
				_buttonPink.addActionListener(this);
				_buttonIndigo.setButtonType(ButtonType::INDIGO);
				_buttonIndigo.setText(L"INDIGO");
				_buttonIndigo.addActionListener(this);
				_buttonOrange.setButtonType(ButtonType::ORANGE);
				_buttonOrange.setText(L"ORANGE");
				_buttonOrange.addActionListener(this);
				_buttonBrown.setButtonType(ButtonType::BROWN);
				_buttonBrown.setText(L"BROWN");
				_buttonBrown.addActionListener(this);
				_buttonSilver.setButtonType(ButtonType::SILVER);
				_buttonSilver.setText(L"SILVER");
				_buttonSilver.addActionListener(this);
				_buttonRed.setButtonType(ButtonType::RED);
				_buttonRed.setText(L"RED");
				_buttonRed.addActionListener(this);
				
				setMinColumnWidth(200);
				addComponent(&_buttonDefault, L"Default Button");
				addComponent(&_buttonPrimary, L"Primary Button");
				addComponent(&_buttonInfo, L"Info Button");
				addComponent(&_buttonDanger, L"Danger Button");
				addComponent(&_buttonSuccess, L"Success Button");
				addComponent(&_buttonWarn, L"Warn Button");
				addComponent(&_buttonBlue, L"Blue Button");
				addComponent(&_buttonLightBlue, L"LighBlue Button");
				addComponent(&_buttonGray, L"Gray Button");
				addComponent(&_buttonLightGray, L"LightGray Button");
				addComponent(&_buttonSilver, L"Silver Button");
				addComponent(&_buttonTeal, L"Teal Button");
				addComponent(&_buttonCyan, L"Cyan Button");
				addComponent(&_buttonPink, L"Pink Button");
				addComponent(&_buttonIndigo, L"Indigo Button");
				addComponent(&_buttonOrange, L"Orange Button");
				addComponent(&_buttonBrown, L"Brown Button");
				addComponent(&_buttonRed, L"Red Button");
				
			}
			~ButtonDemo() {}

		public:

			void onAction(const ActionEvent& ev)
			{
				DialogFactory::showInfo(this, ev.actionName, L"Button Clicked");
			}
		};
										



Button Grid

A **button grid** is a layout component that arranges multiple button elements in a structured, grid-based format. This design pattern is commonly used to display a set of related actions, options, or tools in a visually organized and easily navigable way. Button grids are especially useful in interfaces where users need to make selections quickly or perform tasks from a predefined set—such as in keypads, dashboards, filter menus, or control panels. The grid layout can be responsive, adapting the number of columns and rows based on screen size or container width. Button grids improve usability by grouping actions clearly, reducing cognitive load, and enabling efficient interaction across both desktop and mobile environments.

Button Grid Component
		class ButtonGridDemo: public GridPanel, public ActionListener
		{
			ButtonGrid _buttonGrid;

		public:

			ButtonGridDemo()
			{
				_buttonGrid.setTitle(L"ButtonGrid");
				_buttonGrid.addActionListener(this);
				_buttonGrid.addButton(L"Text-Only");
				_buttonGrid.addButton(L"Disabled");
				_buttonGrid.enableButton(L"Disabled", FALSE);
				_buttonGrid.addButton(L"Add", IconSource(IconType::ADD));
				_buttonGrid.addButton(L"Delete", IconSource(IconType::REMOVE));
				_buttonGrid.addButton(L"Find", IconSource(IconType::BINOCULAR));
				_buttonGrid.addButton(L"Calculate", IconSource(IconType::CALCULATOR));
				_buttonGrid.addButton(L"Attach", IconSource(IconType::ATTACH));
				_buttonGrid.addButton(L"Barcode", IconSource(IconType::BARCODE));
				_buttonGrid.addButton(L"Camera", IconSource(IconType::CAMERA));
				_buttonGrid.addButton(L"Calendar", IconSource(IconType::CALENDAR));
				_buttonGrid.addButton(L"Custom Icon", IconSource(L"deliveryorder.gif"));

				setMargin(0);
				setLayout({ -1 }, { -1 });
				addComponent(&_buttonGrid, 0, 0);
			}
			~ButtonGridDemo(){}

		public:

			void onAction(const ActionEvent& ev)
			{
				DialogFactory::showInfo(this, ev.actionName, L"Button Clicked");
			}
		};
										



Button Menu

A **button menu with text and images** is a user interface component that presents a collection of clickable buttons, each combining an icon or image with a descriptive text label. This design enhances both visual appeal and usability by leveraging imagery to quickly communicate the function or category of each button, while the accompanying text provides clarity and context. Commonly used in navigation menus, dashboards, mobile apps, and feature selectors, this type of menu allows users to easily identify and interact with available options. The layout is presented as a list, and may include hover or active states, making it intuitive and engaging across devices. Ideal for visually-driven interfaces, this component supports accessibility and reinforces recognition over recall, improving overall user experience.

Button Menu Component
		class ButtonMenuDemo : public GridPanel, public SelectionChangeListener
		{
			ButtonMenu _buttonMenu1;
			ButtonMenu _buttonMenu2;

		public:

			ButtonMenuDemo()
			{
				_buttonMenu1.setTitle(L"Button Menu");
				_buttonMenu1.addSelectionChangedListener(this);
				_buttonMenu1.addItem(L"Text-Only");
				_buttonMenu1.addItem(L"Disabled");
				_buttonMenu1.enableItem(L"Disabled", FALSE);
				_buttonMenu1.addItem(L"CheckMark", L"", IconSource(IconType::CHECKMARK));
				_buttonMenu1.addItem(L"Colors", L"", IconSource(IconType::COLORS));
				_buttonMenu1.addItem(L"Clear", L"", IconSource(IconType::CLEAR));
				_buttonMenu1.addItem(L"Category", L"", IconSource(IconType::CATEGORY));
				_buttonMenu1.addItem(L"Department", L"", IconSource(IconType::DEPARTMENT));
				_buttonMenu1.addItem(L"Envelope", L"", IconSource(IconType::ENVELOPE));
				_buttonMenu1.addItem(L"Diamond", L"", IconSource(IconType::DIAMONDKARAT));
				_buttonMenu1.addItem(L"Database", L"", IconSource(IconType::DATABASE));
				_buttonMenu1.addItem(L"Custom Icon", L"", IconSource(L"deliveryorder.gif"));

				_buttonMenu2.setTitle(L"Button Menu - Link Style");
				_buttonMenu2.enableLinkStyle();
				_buttonMenu2.addSelectionChangedListener(this);
				_buttonMenu2.addItem(L"Link 1");
				_buttonMenu2.addItem(L"Disabled");
				_buttonMenu2.addItem(L"Link 3");
				_buttonMenu2.enableItem(L"Disabled", FALSE);
				_buttonMenu2.addItem(L"Link 4", L"");
				_buttonMenu2.addItem(L"Link 5", L"");
				_buttonMenu2.addItem(L"Link 6", L"");
				_buttonMenu2.addItem(L"Link 7", L"");
				_buttonMenu2.addItem(L"Link 8", L"");
				_buttonMenu2.addItem(L"Link 9", L"");
				_buttonMenu2.addItem(L"Link 10", L"");
				_buttonMenu2.addItem(L"Link 11", L"");
				_buttonMenu2.addItem(L"Link 12", L"");

				setMargin(0);
				setLayout({ -1, -1 }, { -1 });
				addComponent(&_buttonMenu1, 0, 0);
				addComponent(&_buttonMenu2, 1, 0);
			}
			~ButtonMenuDemo(){}

		public:

			void onSelectionChanged(const SelectionChangeEvent& ev)
			{
				DialogFactory::showInfo(this, ev.selectionValue, L"Item Selected");
			}
		};
										



Calendar

A **dates calendar** component is a simple and focused UI element that displays the days of a selected month in a grid format, primarily used for date viewing or selection rather than event scheduling. It typically includes navigation controls to move between months and years, and allows users to select a single date or a date range. This type of calendar is commonly used in forms, booking interfaces, or filters where users need to pick a specific date without the complexity of managing events or tasks. Clean and minimal by design, a dates calendar emphasizes usability and clarity, making it easy to browse and choose dates across different devices and screen sizes.

Calendar/Date Picker
		class CalendarDemo : public GridPanel, public SelectionChangeListener
		{
			Calendar _calendar;

		public:

			CalendarDemo()
			{
				_calendar.addSelectionChangedListener(this);

				setMargin(0);
				setLayout({ -1 }, { -1 });
				addComponent(&_calendar, 0, 0);
			}
			~CalendarDemo(){}

		public:

			void onSelectionChanged(const SelectionChangeEvent& ev)
			{
				DialogFactory::showInfo(getWindowHandle(), ev.selectionValue, L"Date Selected");
			}
		};
										



Chart Component

A **charts component** is a visual interface element used to represent data graphically, making complex information easier to understand and analyze at a glance. Common chart types include bar charts, line charts, pie charts, area charts, and scatter plots, each suited for different kinds of data relationships and comparisons. Charts components are often interactive, allowing features like tooltips, legends, filtering, and zooming to enhance user engagement and insight. They are widely used in dashboards, reports, analytics tools, and data-driven applications to highlight trends, distributions, and patterns. Designed with responsiveness and customization in mind, a charts component can adapt to various data sets and screen sizes, delivering a clear and intuitive visual experience.

Chart Component
		class ChartDemo : public GridPanel, public SelectionChangeListener
		{
			Chart _chart;

		public:

			ChartDemo()
			{
				_chart.setType(ChartType::BAR);
				_chart.showTypeToggleButtons(TRUE);
				_chart.setCategories({ L"X1", L"X2", L"X3", L"X4", L"X5", L"X6" });
				_chart.addSeries(L"Series 1", RGB(0, 144, 208));
				_chart.addSeries(L"Series 2", RGB(255, 0, 0));
				_chart.addSeries(L"Series 3", RGB(78, 255, 0));
				// Generate random data
				std::random_device rd;                         // Seed source
				std::mt19937 gen(rd());                        // Mersenne Twister engine
				std::uniform_real_distribution dis(0.0f, 10000.0f); // Range: [0.0, 10000.0)
				for (int s = 0; s < 5; s++)
				{
					_chart.addSeriesValue(L"Series 1", dis(gen), RGB(((int)dis(gen)) % 255, ((int)dis(gen)) % 255, ((int)dis(gen)) % 255));
					_chart.addSeriesValue(L"Series 2", dis(gen), RGB(((int)dis(gen)) % 255, ((int)dis(gen)) % 255, ((int)dis(gen)) % 255));
					_chart.addSeriesValue(L"Series 3", dis(gen), RGB(((int)dis(gen)) % 255, ((int)dis(gen)) % 255, ((int)dis(gen)) % 255));
				}

				setMargin(0);
				setLayout({ -1 }, { -1 });
				addComponent(&_chart, 0, 0);
			}
			~ChartDemo() {}

		public:

			void onSelectionChanged(const SelectionChangeEvent& ev)
			{
			}
		};
										



Check Box

A **checkbox** is a basic form input component that allows users to make binary selections—typically representing a true/false or yes/no choice. It consists of a small square box that can be either checked or unchecked, often accompanied by a label describing the option. Checkboxes are commonly used in forms, settings panels, and filters where multiple options can be selected independently. They support states such as checked, unchecked, and indeterminate (used when a group of related options is only partially selected). Simple, accessible, and easy to interact with, the checkbox is a fundamental UI element for collecting user input in a clear and consistent way.

CheckBox component
		class CheckBoxDemo : public GridPanel, public SelectionChangeListener
		{
			CheckBox _checkBoxText;
			CheckBox _checkBoxNoText;

		public:

			CheckBoxDemo()
			{
				_checkBoxText.setText(L"Employed");
				_checkBoxText.addSelectionChangedListener(this);
				_checkBoxNoText.addSelectionChangedListener(this);

				setLayout({ -1 }, { 30, 30, -1 });
				addComponent(&_checkBoxText, 0, 0);
				addComponent(&_checkBoxNoText, 0, 1);
			}
			~CheckBoxDemo(){}

		public:

			void onSelectionChanged(const SelectionChangeEvent& ev)
			{
				DialogFactory::showInfo(this, ev.selectionValue, L"CheckBox Selection Change");
			}
		};
										



CheckComboBox

A **check combobox** (also known as a multi-select dropdown with checkboxes) is a user interface component that combines the functionality of a dropdown menu and checkboxes, allowing users to select multiple options from a list. When the combobox is clicked, it expands to reveal a list of items, each with an associated checkbox. Users can check or uncheck items independently, and the selected values are typically displayed as a summary (e.g., as text or tags) in the collapsed state of the combobox. This component is ideal for scenarios where space is limited but multiple selections are needed—such as filtering data, selecting tags or categories, or configuring preferences. A check combobox enhances usability by offering a clean, compact design while maintaining the flexibility of multi-selection. Advanced versions may also include features like search, “select all” options, or grouped categories to improve the user experience further.

CheckComboBox component
		class CheckComboBoxDemo : public GridPanel, public SelectionChangeListener
		{
			CheckComboBox _checkComboBox;

		public:

			CheckComboBoxDemo()
			{
				_checkComboBox.setOptions({ {L"CA", L"California"}, {L"FL", L"Florida"} });
				_checkComboBox.addSelectionChangedListener(this);

				setLayout({ -1 }, { 30, -1 });
				addComponent(&_checkComboBox, 0, 0);
			}
			~CheckComboBoxDemo(){}

		public:

			void onSelectionChanged(const SelectionChangeEvent& ev)
			{
				DialogFactory::showInfo(this, ev.selectionValue, L"CheckComboBox Selection Change");
			}
		};
										



CheckList

A **checklist** is a user interface component that displays a list of items, each accompanied by a checkbox, allowing users to mark tasks or options as completed or selected. This component is commonly used for task management, to-do lists, settings configuration, or multi-option selection. Users can check or uncheck each item independently, and the state of each checkbox provides a clear visual indication of progress or selection. Checklists help organize information in a simple, linear format that encourages interaction and improves clarity. They are often enhanced with features like labels, descriptions, grouping, or drag-and-drop reordering. Easy to use and highly intuitive, the checklist is a practical component for both productivity and selection interfaces.

CheckList component
		class CheckListDemo : public GridPanel, public SelectionChangeListener
		{
			CheckList _checkList;

		public:

			CheckListDemo()
			{
				_checkList.setOptions({ {L"CA", L"California"}, {L"FL", L"Florida"} });

				setLayout({ -1 }, { -1 });
				addComponent(&_checkList, 0, 0);
			}
			~CheckListDemo(){}

		public:

			void onSelectionChanged(const SelectionChangeEvent& ev)
			{
				DialogFactory::showInfo(this, ev.selectionValue, L"CheckList Selection Change");
			}
		};
										



ComboBox

A **ComboBox** is a versatile user interface component that combines a dropdown list with a text input field, allowing users to either select an option from a predefined list or enter a custom value. This dual functionality makes it ideal for scenarios where users need flexibility—such as searching through a long list of options or quickly typing in their own input. Typically, when the user clicks on the ComboBox, a dropdown menu appears displaying selectable options. Users can scroll through or type to filter the list dynamically. ComboBoxes are commonly used in forms, search bars, and filtering interfaces to save space while offering both selection and input capabilities. They enhance user experience by balancing ease of choice with the freedom to add new entries.

ComboBox Component
		class ComboBoxDemo : public GridPanel, public SelectionChangeListener
		{
			ComboBox _comboBox;

		public:

			ComboBoxDemo()
			{
				_comboBox.setOptions({ L"California", L"Florida" });
				_comboBox.addSelectionChangedListener(this);

				setLayout({ -1 }, { 30, -1 });
				addComponent(&_comboBox, 0, 0);
			}
			~ComboBoxDemo(){}

		public:

			void onSelectionChanged(const SelectionChangeEvent& ev)
			{
				DialogFactory::showInfo(this, ev.selectionValue, L"ComboBox Selection Change");
			}
		};
										



DatePicker

A **DatePicker dropdown** is a user interface component that allows users to select a date from a calendar interface that appears as a dropdown when interacting with an input field. Instead of typing a date manually, users click or tap on the input box, which triggers a compact calendar popup where they can visually navigate through months and years to pick a specific date. This component improves date entry accuracy and usability by preventing formatting errors and providing an intuitive way to choose dates. DatePicker dropdowns are commonly used in forms, booking systems, and any application requiring date input. They often support features like keyboard navigation, customizable date formats, and restrictions on selectable dates to enhance accessibility and user experience.

DateTimePicker Component
		class DateTimePickerDemo : public GridPanel, public SelectionChangeListener
		{
			DateTimePicker _dateTimePicker;

		public:

			DateTimePickerDemo()
			{
				_dateTimePicker.setSelectedDate(L"1980-12-31");
				_dateTimePicker.addSelectionChangedListener(this);

				setLayout({ -1 }, { 30, -1 });
				addComponent(&_dateTimePicker, 0, 0);
			}
			~DateTimePickerDemo(){}

		public:

			void onSelectionChanged(const SelectionChangeEvent& ev)
			{
				DialogFactory::showInfo(this, ev.selectionValue, L"DateTimePicker Selection Change");
			}
		};
										



Modal Dialog

A **modal dialog** is a UI component that appears as a pop-up window overlaying the main content, requiring the user to interact with it before returning to the underlying interface. It is commonly used to capture user attention for important tasks such as confirming actions, displaying alerts, gathering input, or presenting critical information without navigating away from the current page. Modal dialogs typically include a header, body content, and action buttons (e.g., “Confirm” and “Cancel”). They disable interaction with the background content to focus user engagement and prevent accidental clicks outside the dialog. Well-designed modal dialogs support accessibility features like keyboard navigation and screen reader compatibility, ensuring they are usable by all users.

Modal Popup Dialog
		class DialogDemo : public Dialog, public ActionListener
		{
			Label _targetFileLabel;
			TextField _targetFileField;
			CheckBox _overrideField;

			Button _okButton, _cancelButton;


		public:

			DialogDemo()
			{
			}

			~DialogDemo()
			{
			}

			BOOL windowOpening()
			{
				setTitle(L"Modal Dialog Demo");
				setSize(400, 300);

				GridPanel* contentPane = getContentPane();
				if (contentPane != NULL)
				{
					_okButton.setText(L"OK");
					_okButton.addActionListener(this);
					_cancelButton.setText(L"Cancel");
					_cancelButton.setButtonType(ButtonType::DANGER);
					_cancelButton.addActionListener(this);

					_targetFileLabel.setText(L"Target File:");
					_overrideField.setText(L"Override Existing File");

					contentPane->setLayout({ 20, -1, 90, 90, 20 }, { 20, 30, 30, 30, 10, 30, 20 });
					contentPane->addComponent(&_targetFileLabel, 1, 1, 3);
					contentPane->addComponent(&_targetFileField, 1, 2, 3);
					contentPane->addComponent(&_overrideField, 1, 3, 3);
					contentPane->addComponent(&_okButton, 2, 5);
					contentPane->addComponent(&_cancelButton, 3, 5);
				}
				return TRUE;
			}

			BOOL windowOpened()
			{
				return TRUE;
			}

			BOOL okToClose()
			{
				return TRUE;
			}

			void windowClosed()
			{
			}

			void onAction(const ActionEvent& ev)
			{
				if (ev.sourceComponentId == _okButton.getId())
				{
					close(DIALOG_OK);
				}
				else if (ev.sourceComponentId == _cancelButton.getId())
				{
					close(DIALOG_CANCEL);
				}
			}
		};
										



DialogFactory

A **DialogFactory** is a design pattern or utility component in software development that simplifies the creation and management of dialog components (such as modals, alerts, confirmation dialogs, or input forms) by providing a centralized, reusable way to generate dialogs with consistent styling and behavior. Instead of manually building each dialog from scratch, a DialogFactory abstracts the common setup—like layout, buttons, event handling, and accessibility features—allowing developers to quickly create customized dialogs by specifying only the unique content and actions. This approach promotes code reuse, consistency across the application, and easier maintenance.

DialogFactory Class
		class DialogFactoryDemo : public /*GridPanel*/FluidPanel, public ActionListener
		{
			Component* _parent;

			Button _buttonError;
			Button _buttonWarning;
			Button _buttonInfo;
			Button _buttonSuccess;
			Button _buttonConfirm;
			Button _buttonOpenFile;
			Button _buttonSaveFile;
			Button _buttonSelectFolder;
			Button _buttonSelectColor;
			Button _buttonSelectFont;
			Button _buttonSelectPrinter;
			Button _buttonPrinterSetup;
			Button _buttonInputDialog;

		public:

			DialogFactoryDemo()
			{
				_parent = NULL;

				_buttonError.setButtonType(ButtonType::DANGER);
				_buttonError.setText(L"showError");
				_buttonError.addActionListener(this);
				_buttonWarning.setButtonType(ButtonType::WARN);
				_buttonWarning.setText(L"showWarning");
				_buttonWarning.addActionListener(this);
				_buttonInfo.setButtonType(ButtonType::INFO);
				_buttonInfo.setText(L"showInfo");
				_buttonInfo.addActionListener(this);
				_buttonSuccess.setButtonType(ButtonType::SUCCESS);
				_buttonSuccess.setText(L"showSuccess");
				_buttonSuccess.addActionListener(this);
				_buttonConfirm.setButtonType(ButtonType::GRAY);
				_buttonConfirm.setText(L"showConfirmDialog");
				_buttonConfirm.addActionListener(this);
				_buttonOpenFile.setButtonType(ButtonType::BLUE);
				_buttonOpenFile.setText(L"showOpenFileDialog");
				_buttonOpenFile.addActionListener(this);
				_buttonSaveFile.setButtonType(ButtonType::TEAL);
				_buttonSaveFile.setText(L"showSaveFileDialog");
				_buttonSaveFile.addActionListener(this);
				_buttonSelectFolder.setButtonType(ButtonType::CYAN);
				_buttonSelectFolder.setText(L"showFolderSelectionDialog");
				_buttonSelectFolder.addActionListener(this);
				_buttonSelectColor.setButtonType(ButtonType::PINK);
				_buttonSelectColor.setText(L"showColorSelectionDialog");
				_buttonSelectColor.addActionListener(this);
				_buttonSelectFont.setButtonType(ButtonType::INDIGO);
				_buttonSelectFont.setText(L"showFontSelectionDialog");
				_buttonSelectFont.addActionListener(this);
				_buttonSelectPrinter.setButtonType(ButtonType::ORANGE);
				_buttonSelectPrinter.setText(L"showPrinterSelectionDialog");
				_buttonSelectPrinter.addActionListener(this);
				_buttonPrinterSetup.setButtonType(ButtonType::RED);
				_buttonPrinterSetup.setText(L"showPrinterSetupDialog");
				_buttonPrinterSetup.addActionListener(this);
				_buttonInputDialog.setButtonType(ButtonType::BROWN);
				_buttonInputDialog.setText(L"showInputDialog");
				_buttonInputDialog.addActionListener(this);

				setMinColumnWidth(320);
				setFieldHeight(50);
				addComponent(&_buttonError, L"DialogFactory::showError");
				addComponent(&_buttonWarning, L"DialogFactory::showWarning");
				addComponent(&_buttonInfo, L"DialogFactory::showInfo");
				addComponent(&_buttonSuccess, L"DialogFactory::showSuccess");
				addComponent(&_buttonConfirm, L"DialogFactory::showConfirmDialog");
				addComponent(&_buttonOpenFile, L"DialogFactory::showOpenFileDialog");
				addComponent(&_buttonSaveFile, L"DialogFactory::showSaveFileDialog");
				addComponent(&_buttonSelectFolder, L"DialogFactory::showFolderSelectionDialog");
				addComponent(&_buttonSelectColor, L"DialogFactory::showColorSelectionDialog");
				addComponent(&_buttonSelectFont, L"DialogFactory::showFontSelectionDialog");
				addComponent(&_buttonSelectPrinter, L"DialogFactory::showPrinterSelectionDialog");
				addComponent(&_buttonPrinterSetup, L"DialogFactory::showPrinterSetupDialog");
				addComponent(&_buttonInputDialog, L"DialogFactory::showInputDialog");
			}

			~DialogFactoryDemo()
			{
			}

			void setParent(Component* parent)
			{
				_parent = parent;
			}

			void onAction(const ActionEvent& ev)
			{
				wstring selection;
				COLORREF selectedColor;
				long fontHeight;
				long fontWeight;
				BOOL isItalic;
				long leftMargin, topMargin, rightMargin, bottomMargin;
				vector values;

				if(ev.actionName == L"showError")
					DialogFactory::showError(_parent, L"DialogFactory::"+ev.actionName+L"()", L"Error Dialog");
				else if (ev.actionName == L"showWarning")
					DialogFactory::showWarning(_parent, L"DialogFactory::" + ev.actionName + L"()", L"Warning Dialog");
				else if (ev.actionName == L"showInfo")
					DialogFactory::showInfo(_parent, L"DialogFactory::" + ev.actionName + L"()", L"Info Dialog");
				else if (ev.actionName == L"showSuccess")
					DialogFactory::showSuccess(_parent, L"DialogFactory::" + ev.actionName + L"()", L"Success Dialog");
				else if (ev.actionName == L"showConfirmDialog")
					DialogFactory::showConfirmDialog(_parent, L"DialogFactory::" + ev.actionName + L"()", L"Confirm Dialog");
				else if (ev.actionName == L"showOpenFileDialog")
					DialogFactory::showOpenFileDialog(_parent, selection);
				else if (ev.actionName == L"showSaveFileDialog")
					DialogFactory::showSaveFileDialog(_parent, selection);
				else if (ev.actionName == L"showFolderSelectionDialog")
					DialogFactory::showFolderSelectionDialog(_parent, selection);
				else if (ev.actionName == L"showColorSelectionDialog")
					DialogFactory::showColorSelectionDialog(_parent, selectedColor);
				else if (ev.actionName == L"showFontSelectionDialog")
					DialogFactory::showFontSelectionDialog(_parent, selection, fontHeight, fontWeight, isItalic, selectedColor);
				else if (ev.actionName == L"showPrinterSelectionDialog")
					DialogFactory::showPrinterSelectionDialog(_parent);
				else if (ev.actionName == L"showPrinterSetupDialog")
					DialogFactory::showPrinterSetupDialog(_parent, leftMargin, topMargin, rightMargin, bottomMargin);
				else if (ev.actionName == L"showInputDialog")
					DialogFactory::showInputDialog(_parent, { L"Name:", L"Address",L"City", L"State",L"Zipcode" }, values);
			}
		};
										



FluidPanel

The FluidPanel is a layout management component that can be used to display components from left-to-right, with the responsive capability built-in, you simply set the minimum width of a column, and the component takes care of laying out the child components in a responsive manner.

FluidPanel Layout manager
		class FluidPanelDemo : public FluidPanel
		{
			Image _image;
			TextField _textField;
			TextField _passwordField;
			MaskedField _maskedField;
			ToggleButton _toggleButton;
			Switch _switch;
			Slider _slider;
			ComboBox _comboField;
			CheckComboBox _checkComboField;
			Radio _radioField;
			ListBox _listboxField;
			CheckBox _checkBox;
			Rating _rating;

		public:

			FluidPanelDemo()
			{
				setMinColumnWidth(250);
				setFieldHeight(70);

				_image.setImage(L"c:\\ezpointofsale\\images\\closeshift.gif");
				_image.setAlignment(ImageAlignment::MIDDLECENTER);
				addComponent(&_image, L"");
				addComponent(&_textField, L"TextField");
				_passwordField.setPassword(TRUE);
				addComponent(&_passwordField, L"PasswordField");
				_maskedField.setMask(L"(###) ###-####");// L"(###) ###-####");
				addComponent(&_maskedField, L"MaskedField");

				_switch.setOptions(L"Male", L"Female");
				addComponent(&_switch, L"Switch");
				addComponent(&_slider, L"Slider");
				_toggleButton.setOptions({ L"Male", L"Female", L"Unspecified" });
				addComponent(&_toggleButton, L"ToggleButton");
				_checkBox.setText(L"CheckBox");
				addComponent(&_checkBox, L"CheckBox");
				addComponent(&_rating, L"Rating");
				_comboField.setOptions({ L"HKEY_LOCAL_MACHINE",L"HKEY_CURRENT_USER" });
				addComponent(&_comboField, L"ComboBox");
				vector selections;
				for (int i = 1; i < 100; i++)
				{
					wchar_t actionId[50];
					_itow_s(i, actionId, 49, 10);
					selections.push_back(KeyValue(actionId, wstring(L"Item ") + actionId));
				}
				_checkComboField.setOptions(selections);
				addComponent(&_checkComboField, L"CheckComboBox");
				_radioField.setOrientation(L"VERT");
				_radioField.addOption(L"M", L"Male");
				_radioField.addOption(L"F", L"Female");
				_radioField.addOption(L"U", L"Unknown");
				addComponent(&_radioField, L"Radio");
				_listboxField.addItem(L"HKEY_LOCAL_MACHINE");
				_listboxField.addItem(L"HKEY_CURRENT_USER");
				addComponent(&_listboxField, L"ListBox");
			}
			~FluidPanelDemo(){}
		};
										



GridPanel

A **responsive container panel** is a versatile UI component designed to automatically adjust its size, layout, and content arrangement based on the screen size or device viewport. It acts as a flexible wrapper or section that can contain other elements—such as text, images, or controls—and ensures they are displayed optimally on desktops, tablets, and mobile devices. Responsive container panels use fluid grids, flexible widths, and media queries (in web design) or adaptive layout techniques to reorganize content, resize components, and maintain usability across different screen dimensions. They are essential for building modern, mobile-friendly interfaces that provide a consistent and user-friendly experience regardless of how users access the application or website.

GridPanel Layout manager
		class GridPanelDemo : public GridPanel, public ActionListener
		{
			Image _image;
			Label _textFieldLabel;
			TextField _textField;
			Label _passwordFieldLabel;
			TextField _passwordField;
			Label _maskedFieldLabel;
			MaskedField _maskedField;
			Label _toggleButtonLabel;
			ToggleButton _toggleButton;
			Label _switchLabel;
			Switch _switch;
			Label _sliderLabel;
			Slider _slider;
			Label _comboFieldLabel;
			ComboBox _comboField;
			CheckComboBox _checkComboField;
			Label _radioFieldLabel;
			Radio _radioField;
			Label _listboxFieldLabel;
			ListBox _listboxField;
			CheckBox _checkBox;
			Rating _rating;
			Chart _chart;
			Button _openFileDialog, _saveFileDialog, _selectFolderDialog, _selectFontDialog, _selectColorDialog, _selectPrinterDialog, _pageSetupDialog;

		public:

			GridPanelDemo()
			{
				vector rows;

				rows.push_back(20);

				_image.setImage(L"c:\\ezpointofsale\\images\\closeshift.gif");
				_image.setAlignment(ImageAlignment::MIDDLECENTER);
				addComponent(&_image, 3, 1, 1, 3);

				rows.push_back(FluidPanel::HEIGHT_TEXTFIELD);
				_textFieldLabel.setText(L"Text Field");
				addComponent(&_textFieldLabel, 1, rows.size() - 1);
				rows.push_back(FluidPanel::HEIGHT_TEXTFIELD);
				addComponent(&_textField, 1, rows.size() - 1);

				rows.push_back(FluidPanel::HEIGHT_TEXTFIELD);
				_passwordFieldLabel.setText(L"Password Field");
				addComponent(&_passwordFieldLabel, 1, rows.size() - 1);
				rows.push_back(FluidPanel::HEIGHT_TEXTFIELD);
				_passwordField.setPassword(TRUE);
				addComponent(&_passwordField, 1, rows.size() - 1);

				rows.push_back(FluidPanel::HEIGHT_TEXTFIELD);
				_maskedFieldLabel.setText(L"Masked Field");
				addComponent(&_maskedFieldLabel, 1, rows.size() - 1);
				rows.push_back(FluidPanel::HEIGHT_TEXTFIELD);
				_maskedField.setMask(L"(###) ###-####");// L"(###) ###-####");
				addComponent(&_maskedField, 1, rows.size() - 1);

				rows.push_back(300);
				_chart.setType(ChartType::PIE);
				_chart.showTypeToggleButtons(TRUE);
				_chart.setCategories({ L"X1", L"X2", L"X3", L"X4", L"X5", L"X6", L"X7", L"X8", L"X9", L"X10" });
				_chart.addSeries(L"Series 1", RGB(0, 0, 200));
				_chart.addSeries(L"Series 2", RGB(255, 0, 0));
				_chart.addSeries(L"Series 3", RGB(0, 128, 0));
				// Generate random data
				std::random_device rd;                         // Seed source
				std::mt19937 gen(rd());                        // Mersenne Twister engine
				std::uniform_real_distribution dis(0.0f, 10000.0f); // Range: [0.0, 10000.0)
				for (int s = 0; s < 10; s++)
				{
					_chart.addSeriesValue(L"Series 1", dis(gen), RGB(((int)dis(gen)) % 255, ((int)dis(gen)) % 255, ((int)dis(gen)) % 255));
					_chart.addSeriesValue(L"Series 2", dis(gen), RGB(((int)dis(gen)) % 255, ((int)dis(gen)) % 255, ((int)dis(gen)) % 255));
					_chart.addSeriesValue(L"Series 3", dis(gen), RGB(((int)dis(gen)) % 255, ((int)dis(gen)) % 255, ((int)dis(gen)) % 255));
				}
				addComponent(&_chart, 1, rows.size() - 1);

				rows.push_back(FluidPanel::HEIGHT_TEXTFIELD);
				_switchLabel.setText(L"Switch");
				addComponent(&_switchLabel, 1, rows.size() - 1);
				rows.push_back(FluidPanel::HEIGHT_TEXTFIELD);
				_switch.setOptions(L"Male", L"Female");
				addComponent(&_switch, 1, rows.size() - 1);

				rows.push_back(FluidPanel::HEIGHT_TEXTFIELD);
				_sliderLabel.setText(L"Slider");
				addComponent(&_sliderLabel, 1, rows.size() - 1);
				rows.push_back(FluidPanel::HEIGHT_TEXTFIELD);
				addComponent(&_slider, 1, rows.size() - 1);

				rows.push_back(FluidPanel::HEIGHT_TEXTFIELD);
				_toggleButtonLabel.setText(L"Toggle Button");
				addComponent(&_toggleButtonLabel, 1, rows.size() - 1);
				rows.push_back(FluidPanel::HEIGHT_TEXTFIELD);
				_toggleButton.setOptions({ L"Male", L"Female", L"Unspecified" });
				addComponent(&_toggleButton, 1, rows.size() - 1);

				rows.push_back(FluidPanel::HEIGHT_TEXTFIELD);
				_checkBox.setText(L"CheckBox");
				addComponent(&_checkBox, 1, rows.size() - 1);

				rows.push_back(FluidPanel::HEIGHT_TEXTFIELD);
				addComponent(&_rating, 1, rows.size() - 1);

				rows.push_back(FluidPanel::HEIGHT_TEXTFIELD);
				_comboFieldLabel.setText(L"ComboBox");
				addComponent(&_comboFieldLabel, 1, rows.size() - 1);
				rows.push_back(FluidPanel::HEIGHT_COMBOBOX);
				_comboField.setOptions({ L"HKEY_LOCAL_MACHINE",L"HKEY_CURRENT_USER" });
				addComponent(&_comboField, 1, rows.size() - 1);

				rows.push_back(FluidPanel::HEIGHT_COMBOBOX);
				vector selections;
				for (int i = 1; i < 100; i++)
				{
					wchar_t actionId[50];
					_itow_s(i, actionId, 49, 10);
					selections.push_back(KeyValue(actionId, wstring(L"Item ") + actionId));
				}
				_checkComboField.setOptions(selections);
				addComponent(&_checkComboField, 1, rows.size() - 1);

				rows.push_back(FluidPanel::HEIGHT_TEXTFIELD);
				_radioFieldLabel.setText(L"Radio Group");
				addComponent(&_radioFieldLabel, 1, rows.size() - 1);
				rows.push_back(50);
				_radioField.setOrientation(L"VERT");
				_radioField.addOption(L"M", L"Male");
				_radioField.addOption(L"F", L"Female");
				_radioField.addOption(L"U", L"Unknown");
				addComponent(&_radioField, 1, rows.size() - 1);

				rows.push_back(FluidPanel::HEIGHT_TEXTFIELD);
				_listboxFieldLabel.setText(L"ListBox");
				addComponent(&_listboxFieldLabel, 1, rows.size() - 1);
				rows.push_back(100);
				_comboField.setOptions({ L"HKEY_LOCAL_MACHINE",L"HKEY_CURRENT_USER" });
				_listboxField.addItem(L"HKEY_LOCAL_MACHINE");
				_listboxField.addItem(L"HKEY_CURRENT_USER");
				addComponent(&_listboxField, 1, rows.size() - 1);
				rows.push_back(20);

				_openFileDialog.setText(L"Open File");
				_openFileDialog.addActionListener(this);
				addComponent(&_openFileDialog, 3, 8);
				_saveFileDialog.setText(L"Save File");
				addComponent(&_saveFileDialog, 3, 9);
				_selectFolderDialog.setText(L"Select Folder");
				addComponent(&_selectFolderDialog, 3, 10);
				_selectFontDialog.setText(L"Select Font");
				addComponent(&_selectFontDialog, 3, 11);
				_selectColorDialog.setText(L"Select Color");
				addComponent(&_selectColorDialog, 3, 12);
				_selectPrinterDialog.setText(L"Select Printer");
				addComponent(&_selectPrinterDialog, 3, 13);
				_pageSetupDialog.setText(L"Printer Setup");
				addComponent(&_pageSetupDialog, 3, 14);

				setLayout({ 50, -1 , 10, 100, 50 }, rows);
			}

			~GridPanelDemo()
			{
			}

			void onAction(const ActionEvent& ev)
			{
				wstring selection;
				if (ev.actionName == L"Open File")
					DialogFactory::showOpenFileDialog(this, selection);
			}
		};
										



Grid

The grid component is a table component that displays rows of data, you can configure the columns, their width, their editable state, etc. You can also enable paging by implementing a paging interface, and then you implement a function that the grid will call each time it needs to fetch a page.

Grid Component
		class GridDemoData
		{
		public:
			wstring name;
			double regularhours;
			double regularrate;
			double overtimehours;
			double overtimerate;
			double taxrate;
		};
		class GridDemo : public GridPanel, public Pager, public GridChangeListener
		{
			Grid _grid;
			vector< GridDemoData> _data;

		public:

			GridDemo()
			{
				_grid.addColumn(L"Name", L"Name", TRUE, 30, -1, FALSE, FALSE, TRUE);
				_grid.addColumn(L"RegularHours", L"Regular Hours", TRUE, 10, 1, TRUE, FALSE, TRUE);
				_grid.addColumn(L"RegularRate", L"Regular Rate", TRUE, 10, 1, TRUE, FALSE, TRUE);
				_grid.addColumn(L"OvertimeHours", L"Overtime Hours", TRUE, 10, 1, TRUE, FALSE, TRUE);
				_grid.addColumn(L"OvertimeRate", L"Overtime Rate", TRUE, 10, 1, TRUE, FALSE, TRUE);
				_grid.addColumn(L"TaxRate", L"Tax Rate", TRUE, 10, 1, TRUE, FALSE, TRUE);
				_grid.addColumn(L"GrossPay", L"Gross Pay", TRUE, 10, 1, TRUE, FALSE, FALSE, EditType::COMPUTED, {}, L"regularhours*regularrate + overtimehours*overtimerate");
				_grid.addColumn(L"NetPay", L"Net Pay", TRUE, 10, 1, TRUE, FALSE, FALSE, EditType::COMPUTED, {}, L"(regularhours*regularrate + overtimehours*overtimerate) - (regularhours*regularrate + overtimehours*overtimerate)*taxrate / 100.0");
				_grid.setPager(this);
				_grid.addGridChangeListener(this);

				setLayout({ -1 }, { -1 });
				addComponent(&_grid, 0, 0);

				// Load sample data
				for (__int64 row = 0; row < 1000; row++)
				{
					GridDemoData newRow;
					wchar_t sNo[50];
					_itow_s(row + 1, sNo, 49, 10);
					newRow.name = wstring(L"Name-") + sNo;
					newRow.regularhours = 40;
					newRow.regularrate = (row%2) == 0 ? 20: 10;
					newRow.overtimehours = (row % 2) == 0 ? 0 : 2;
					newRow.overtimerate = (row % 2) == 0 ? 30 : 25;
					newRow.taxrate = 25;

					_data.push_back(newRow);
				}
			}

			~GridDemo()
			{
			}

			BOOL GetPage(const PagerRequest& request, const vector& columnNames, vector>& rows, __int64& totalRowCount)
			{
				if (request.startRowIndex >= 0 && request.startRowIndex < _data.size())
				{
					/*
					if (request.sortBy.length() > 0)
					{
						if (request.sortBy == L"Name") {
							if (request.sortDirection == SortType::DESCENDING) {
								std::sort(_data.begin(), _data.end(), [](const GridDemoData& a, const GridDemoData& b) {
									return a.name > b.name;
									});
							}
							else {
								std::sort(_data.begin(), _data.end(), [](const GridDemoData& a, const GridDemoData& b) {
									return a.name < b.name;
									});
							}
						} else if (request.sortBy == L"City") {
							if (request.sortDirection == SortType::DESCENDING) {
								std::sort(_data.begin(), _data.end(), [](const GridDemoData& a, const GridDemoData& b) {
									return a.city > b.city;
									});
							}
							else {
								std::sort(_data.begin(), _data.end(), [](const GridDemoData& a, const GridDemoData& b) {
									return a.city < b.city;
									});
							}
						}
						else if (request.sortBy == L"State") {
							if (request.sortDirection == SortType::DESCENDING) {
								std::sort(_data.begin(), _data.end(), [](const GridDemoData& a, const GridDemoData& b) {
									return a.state > b.state;
								});
							}
							else {
								std::sort(_data.begin(), _data.end(), [](const GridDemoData& a, const GridDemoData& b) {
									return a.state < b.state;
									});
							}
						}
						else if (request.sortBy == L"Employed") {
							if (request.sortDirection == SortType::DESCENDING) {
								std::sort(_data.begin(), _data.end(), [](const GridDemoData& a, const GridDemoData& b) {
									return a.employed > b.employed;
									});
							}
							else {
								std::sort(_data.begin(), _data.end(), [](const GridDemoData& a, const GridDemoData& b) {
									return a.employed < b.employed;
									});
							}
						}
						else if (request.sortBy == L"HireDate") {
							if (request.sortDirection == SortType::DESCENDING) {
								std::sort(_data.begin(), _data.end(), [](const GridDemoData& a, const GridDemoData& b) {
									return a.hiredate > b.hiredate;
									});
							}
							else {
								std::sort(_data.begin(), _data.end(), [](const GridDemoData& a, const GridDemoData& b) {
									return a.hiredate < b.hiredate;
									});
							}
						}
					}
					*/
					rows.clear();
					for (__int64 row = request.startRowIndex; row < (request.startRowIndex + request.pageSize); row++)
					{
						if (row >= 0 && row < _data.size())
						{
							wchar_t s[255];
							vector newRow;
							for (int col = 0; col < columnNames.size(); col++)
							{
								if(columnNames[col] == L"Name")
									newRow.push_back(_data[row].name);
								else if (columnNames[col] == L"RegularHours")
								{
									swprintf(s, 255,  L"%0.2f", _data[row].regularhours);
									newRow.push_back(s);
								}
								else if (columnNames[col] == L"RegularRate")
								{
									swprintf(s, 255, L"%0.2f", _data[row].regularrate);
									newRow.push_back(s);
								}
								else if (columnNames[col] == L"OvertimeHours")
								{
									swprintf(s, 255, L"%0.2f", _data[row].overtimehours);
									newRow.push_back(s);
								}
								else if (columnNames[col] == L"OvertimeRate")
								{
									swprintf(s, 255, L"%0.2f", _data[row].overtimerate);
									newRow.push_back(s);
								}
								else if (columnNames[col] == L"TaxRate")
								{
									swprintf(s, 255, L"%0.2f", _data[row].taxrate);
									newRow.push_back(s);
								}
							}
							rows.push_back(newRow);
						}
						else
							break;
					}
				}
				totalRowCount = _data.size();

				return TRUE;
			}

			BOOL onCellValueChanged(long sourceId, __int64 rowIndex, const wstring& columnName,
				const wstring& oldValue, const wstring& newValue)
			{
				/*
				if (oldValue != newValue)
				{
					if (rowIndex >= 0 && rowIndex < _data.size())
					{
						if (columnName == L"Name")
							_data[rowIndex].name = newValue;
						else if (columnName == L"City")
							_data[rowIndex].city = newValue;
						else if (columnName == L"State")
							_data[rowIndex].state = newValue;
						else if (columnName == L"Employed")
							_data[rowIndex].employed = newValue;
						else if (columnName == L"HireDate")
							_data[rowIndex].hiredate = newValue;
						return TRUE;
					}
				}
				*/
				return FALSE;
			}
		};
										



GridView

A **grid table** is a structured UI component that displays data in a tabular format using a grid layout of rows and columns. Each cell in the table holds individual pieces of information, allowing users to easily scan, compare, and analyze data. Grid tables often include features such as sortable columns, filtering, pagination, and selectable rows to enhance data interaction and usability. Commonly used in dashboards, data management systems, and reporting tools, grid tables provide a clear and organized way to present complex datasets. They can be styled for readability with alternating row colors, fixed headers, and responsive behavior to adapt across different screen sizes and devices.

GridView Component
		class GridViewDemo : public GridPanel, public GridViewListener
		{
			GridView _gridView;

		public:

			GridViewDemo()
			{
				_gridView.addColumn(L"TargetFile",L"Target File", TRUE, -1);
				_gridView.addColumn(L"Overwrite", L"Overwrite", TRUE, 100);
				_gridView.setListener(this);
				_gridView.enableInlineEditing(TRUE);

				setLayout({ -1 }, { -1 });
				addComponent(&_gridView, 0, 0);
			}

			~GridViewDemo()
			{
			}

			void onCreateItem(long sourceId)
			{
				/*
				FileEntryDialog dlg;

				dlg.setVisible(getWindowHandle());
				if (dlg.getExitCode() == DIALOG_OK)
				{
					long rowIndex = _filesPanel.addRow();
					if (rowIndex >= 0)
					{
						_filesPanel.setCellValue(rowIndex, 0, dlg._targetFile);
						_filesPanel.setCellValue(rowIndex, 1, dlg._override ? L"Yes" : L"No");
					}
				}
				*/
			}

			void onEditItem(long sourceId, __int64 rowIndex)
			{
				/*
				FileEntryDialog dlg;

				dlg._targetFile = _filesPanel.getCellValue(rowIndex, 0);
				dlg._override = _filesPanel.getCellValue(rowIndex, 1) == L"Yes";

				dlg.setVisible(getWindowHandle());
				if (dlg.getExitCode() == DIALOG_OK)
				{
					_filesPanel.setCellValue(rowIndex, 0, dlg._targetFile);
					_filesPanel.setCellValue(rowIndex, 1, dlg._override ? L"Yes" : L"No");
				}
				*/
			}

			BOOL onDeleteItem(long sourceId, __int64 rowIndex)
			{
				if (MessageBox(NULL, L"Are you sure you want to delete the selected file?", L"Confirm Deletion", MB_YESNO) == IDYES)
				{
					// TODO: Delete the row
					return TRUE;
				}
				return FALSE;
			}

			void onItemCreated(long sourceId, __int64 rowIndex, const vector& rowValues)
			{

			}

			void onItemUpdated(long sourceId, __int64 rowIndex, const vector& rowValues)
			{

			}
		};
										



IconMenu

A **vertical icon menu** is a user interface component that displays a series of clickable icons arranged in a single vertical column. Each icon represents a distinct action, tool, or navigation option, providing users with a space-efficient and visually clear way to access features or pages. This vertical alignment is especially useful for sidebars, navigation panels, or tool palettes where screen width is limited or where a natural top-to-bottom flow enhances usability. Vertical icon menus often include hover or focus states, and sometimes labels or tooltips to clarify icon meanings, improving accessibility. They help organize functionality in a neat, easily scannable format, making them ideal for both desktop and mobile interfaces.

IconMenu Component
		class IconMenuDemo : public GridPanel, public SelectionChangeListener
		{
			IconMenu _iconMenu;

		public:

			IconMenuDemo()
			{
				_iconMenu.setTitle(L"Icon Menu - Pinnable");
				for (long i = 1; i < 100; i++)
				{
					wchar_t szText[255];
					swprintf_s(szText, 254, L"Icon %d", i);
			//        _iconMenu.addItem(L"C:/EzPointOfSale/images/closeshift.gif", szText);
					_iconMenu.addItem(IDR_LOGO_PNG, ImageType::PNG, szText);
				}
			//    _iconMenu.setPinnable(TRUE);
				_iconMenu.addSelectionChangedListener(this);

				setLayout({ -1 }, { -1 });
				addComponent(&_iconMenu, 0, 0);
			}

			~IconMenuDemo()
			{
			}

			void onSelectionChanged(const SelectionChangeEvent& ev)
			{
				DialogFactory::showInfo(this, ev.selectionValue, L"Icon Menu Selection");
			}
		};
										



Image

An **image** component is a fundamental UI element used to display visual content such as photographs, illustrations, icons, or graphics within an application or webpage. Images enhance the user experience by providing context, conveying information quickly, and adding aesthetic appeal. This component typically supports various formats (JPEG, PNG, GIF, etc.) and can be customized with properties like size, alignment, alt text for accessibility, captions, and responsive behavior to adapt to different screen sizes. Proper use of images improves engagement, clarifies content, and complements text-based information effectively.

Image Component
		class ImageDemo : public GridPanel
		{
			Image _imagePng, _imageGif, _imageJpg;

		public:

			ImageDemo()
			{
				_imagePng.setImage(IDR_LOGO_PNG, ImageType::PNG);
				_imageJpg.setImage(IDR_LOGO_JPG, ImageType::JPG);
				_imageGif.setImage(IDR_LOGO_GIF, ImageType::GIF);

				setLayout({ 128, 128, -1 }, { 128, 20, 128, 20, 128, -1 });
				addComponent(&_imagePng, 1, 0);
				addComponent(&_imageJpg, 1, 2);
				addComponent(&_imageGif, 1, 4);
			}

			~ImageDemo()
			{
			}
		};
										



Label

A **text label** is a simple user interface component that displays static text to identify, describe, or provide context for other UI elements such as input fields, buttons, icons, or sections. Labels help users understand the purpose or content of an element, improving clarity and usability. Text labels are usually concise, clearly visible, and positioned close to the related component. They can include styling options like font size, color, and weight to enhance readability and hierarchy. Accessible labels also play a crucial role in supporting screen readers and assistive technologies, making interfaces more inclusive.

Label Component
		class LabelDemo : public GridPanel
		{
			Label _label1;
			Label _label2;
			Label _label3;
			Label _label4;

		public:

			LabelDemo()
			{
				_label1.setAlignment(-1);
				_label1.setText(L"Left-aligned Label");
				_label2.setAlignment(0);
				_label2.setText(L"Center-aligned Label");
				_label3.setAlignment(1);
				_label3.setText(L"Right-aligned Label");
				_label4.setAlignment(0);
				_label4.setFont(20, TRUE, TRUE, TRUE);
				_label4.setText(L"Styled Label");

				setLayout({ -1,-1 }, { 30,30,60, -1 });
				addComponent(&_label4, 0, 0, 2);
				addComponent(&_label1, 0, 1);
				addComponent(&_label3, 1, 1);
				addComponent(&_label2, 0, 2, 2);
			}

			~LabelDemo()
			{
			}
		};
										



ListBox

A **listbox** is a user interface component that displays a scrollable list of items from which users can select one or multiple options. It typically shows several items at once, allowing users to navigate through the list using a mouse, or keyboard, input. Listboxes are commonly used in forms, settings panels, and selection dialogs where presenting a large set of choices in a compact, easy-to-scan format is needed. They can support single or multiple selection modes and often include features like search, grouping, and keyboard navigation to improve usability and accessibility.

ListBox Component
		class ListBoxDemo : public GridPanel, public SelectionChangeListener
		{
			ListBox _listbox;

		public:

			ListBoxDemo()
			{
				_listbox.addItem(L"Manager"); 
				_listbox.addItem(L"Sales Representative"); 
				_listbox.addItem(L"Cashier");
				_listbox.addItem(L"Security");
				_listbox.addItem(L"Clerk");
				_listbox.addItem(L"Accountant");
				_listbox.addItem(L"CEO");
				_listbox.addSelectionChangedListener(this);

				setLayout({ -1 }, { 100, -1 });
				addComponent(&_listbox, 0, 0);
			}

			~ListBoxDemo()
			{
			}

			void onSelectionChanged(const SelectionChangeEvent& ev)
			{
				DialogFactory::showInfo(this, ev.selectionValue, L"ListBox Selection Change");
			}
		};
										



MaskedField

A **masked field** is an input component that enforces a specific format or pattern for user-entered data by visually guiding or restricting input as it’s typed. It “masks” the input by automatically adding characters like parentheses, dashes, or slashes, or by limiting the type and number of characters, ensuring data consistency and reducing input errors. Common examples include phone numbers, dates, credit card numbers, social security numbers, and postal codes. Masked fields improve user experience by making it clear how information should be entered and help applications validate data more efficiently.

MaskedField Component
		class MaskedFieldDemo : public GridPanel
		{
			Label _label1, _label2, _label3;
			MaskedField _maskedField1;
			MaskedField _maskedField2;
			MaskedField _maskedField3;

		public:

			MaskedFieldDemo()
			{
				_label1.setAlignment(-1);
				_label1.setText(L"Input Format: (###) ###-####");
				_maskedField1.setMask(L"(###) ###-####");
				_label2.setAlignment(-1);
				_label2.setText(L"Input Format: @-#######");
				_maskedField2.setMask(L"@-#######");
				_label3.setAlignment(-1);
				_label3.setText(L"Input Format: SSN ###-##-####");
				_maskedField3.setMask(L"SSN ###-##-####");

				setLayout({ -1 }, { 30,30,30,30,30,30, -1 });
				addComponent(&_label1, 0, 0);
				addComponent(&_maskedField1, 0, 1);
				addComponent(&_label2, 0, 2);
				addComponent(&_maskedField2, 0, 3);
				addComponent(&_label3, 0, 4);
				addComponent(&_maskedField3, 0, 5);
			}

			~MaskedFieldDemo()
			{
			}
		};
										



PickList

A **picklist with two lists** (also known as a dual-listbox or multi-select transfer list) is a UI component that displays two side-by-side lists—one showing available options and the other showing selected items. Users can move items back and forth between the lists using buttons, allowing easy selection and management of multiple choices from a larger pool. This component is ideal for scenarios where users need to select multiple options without cluttering the interface, such as assigning users to groups, selecting preferences, or managing features. The dual-list layout provides clear visual separation between chosen and unchosen items, improving usability and control over selections.

PickList Component
		class PickListDemo : public GridPanel
		{
			PickList _pickList;

		public:

			PickListDemo()
			{
				vector selectableItems, selectedItems;
				selectableItems.push_back(KeyValue(L"1", L"California"));
				selectableItems.push_back(KeyValue(L"2", L"Florida"));
				selectableItems.push_back(KeyValue(L"3", L"Georgia"));
				selectableItems.push_back(KeyValue(L"4", L"Arizona"));
				selectableItems.push_back(KeyValue(L"5", L"Texas"));

				_pickList.setSelectableItems(selectableItems);
				_pickList.setSelectedItems(selectedItems);

				setLayout({ -1 }, { -1 });
				addComponent(&_pickList, 0, 0);
			}

			~PickListDemo()
			{
			}
		};
										



PopupMenu

A **popup menu** is a contextual user interface element that appears temporarily on top of the current screen or application content, typically triggered by a right-click, tap, or specific user interaction. It presents a list of options or actions relevant to the current context, allowing users to quickly choose commands without navigating away from their current task. Popup menus are commonly used for shortcuts, tool options, or additional settings, and often disappear automatically after a selection is made or when the user clicks outside the menu. Designed to be lightweight and unobtrusive, popup menus enhance usability by providing quick access to contextual functions while keeping the interface clean.

PopupMenu
		class PopupMenuDemo : public GridPanel, public ActionListener
		{
			Button _trigger;

		public:

			PopupMenuDemo()
			{
				_trigger.setText(L"Show Popup Menu");
				_trigger.addActionListener(this);

				setLayout({ -1, 300, -1 }, { -1, 35, -1 });
				addComponent(&_trigger, 1, 1);
			}

			~PopupMenuDemo()
			{
			}

			void onAction(const ActionEvent& ev)
			{
				if (ev.sourceComponentId == _trigger.getId())
				{
					PopupMenu pMenu;
					pMenu.addItem(1, L"Add");
					pMenu.addItem(2, L"Edit");
					pMenu.addSeparator();
					pMenu.addItem(3, L"Delete");

					Bounds rect;
					_trigger.GetWindowRect(rect);
					POINT pt = { rect.left, rect.bottom };
					ScreenToClient(getWindowHandle(), &pt);
					long selection = pMenu.showMenu(getWindowHandle(), pt.x, pt.y);
					if (selection == 1) {
						DialogFactory::showInfo(this, L"Add", L"Selection");
					}
					else if (selection == 2) {
						DialogFactory::showInfo(this, L"Edit", L"Selection");
					}
					else if (selection == 3) {
						DialogFactory::showInfo(this, L"Delete", L"Selection");
					}
				}
			}
		};
										



ProgressBar

A **progress bar** is a visual UI component that indicates the completion status of a task or process over time. It typically appears as a horizontal or circular bar that fills up proportionally to show progress, helping users understand how much of the task is done and how much remains. Progress bars are commonly used in file uploads, installations, loading screens, and any operation where feedback on time or completion percentage improves user experience. They can be determinate (showing exact progress) or indeterminate (indicating ongoing activity without a specific percentage), and often include animations, labels, or percentages to enhance clarity and engagement.

ProgressBar Component
		class ProgressBarDemo : public GridPanel, public ActionListener
		{
			Label _label;
			ProgressBar _progressBar;
			unsigned int timerId;
			int timerValue;

			Button _startBtn, _stopBtn;

		public:

			ProgressBarDemo()
			{
				timerId = 100001;
				timerValue = 0;

				_label.setText(L"Progress Bar");
				_label.setAlignment(-1);

				_startBtn.setText(L"Start");
				_startBtn.addActionListener(this);
				_stopBtn.setText(L"Stop");
				_stopBtn.addActionListener(this);

				setLayout({ 100, 5, 100, -1 }, { 35, 35, 10, 30, -1 });
				addComponent(&_label, 0, 0, 4);
				addComponent(&_progressBar, 0, 1, 4);
				addComponent(&_startBtn, 0, 3);
				addComponent(&_stopBtn, 2, 3);
			}

			~ProgressBarDemo()
			{
				stopTimer(timerId);
			}

			void onAction(const ActionEvent& ev)
			{
				if (ev.actionName == L"Start")
				{
					timerValue = 0;
					startTimer(timerId, 250);
				}
				else if(ev.actionName == L"Stop")
					stopTimer(timerId);
			}

			void onTimer(unsigned int timerId)
			{
				if (timerValue > 100)
					stopTimer(timerId);
				else
				{
					timerValue++;
					_progressBar.setValue(timerValue);
				}
			}
		};
										



Radio

A **radio group** is a user interface component that presents a set of related options where only one option can be selected at a time. It consists of multiple radio buttons grouped together, each representing a single choice within a category. Selecting one radio button automatically deselects any previously selected option in the same group. Radio groups are commonly used in forms and surveys to gather exclusive choices—such as gender selection, payment methods, or preference settings. They improve clarity by visually grouping mutually exclusive options, and when properly labeled, they enhance accessibility for all users.

Radio Component
		class RadioDemo : public GridPanel, public SelectionChangeListener
		{
			Label _labelVert;
			Radio _radioGroupVert;
			Label _labelHorz;
			Radio _radioGroupHorz;

		public:

			RadioDemo()
			{
				_labelHorz.setText(L"Horizontal Orientation:");
				addComponent(&_labelHorz, 0, 0);
				_radioGroupHorz.setOrientation(L"HORZ");
				_radioGroupHorz.addOption(L"M", L"Male");
				_radioGroupHorz.addOption(L"F", L"Female");
				_radioGroupHorz.addOption(L"U", L"Unknown");
				_radioGroupHorz.addSelectionChangedListener(this);
				addComponent(&_radioGroupHorz, 0, 1);

				_labelVert.setText(L"Verical Orientation:");
				addComponent(&_labelVert, 0, 3);
				_radioGroupVert.setOrientation(L"VERT");
				_radioGroupVert.addOption(L"M", L"Male");
				_radioGroupVert.addOption(L"F", L"Female");
				_radioGroupVert.addOption(L"U", L"Unknown");
				_radioGroupVert.addSelectionChangedListener(this);
				addComponent(&_radioGroupVert, 0,4);

				setLayout({ -1 }, { 30, 30, 50, 30, 100, -1 });
			}

			~RadioDemo()
			{
			}

			void onSelectionChanged(const SelectionChangeEvent& ev)
			{
				DialogFactory::showInfo(this, ev.selectionValue, L"Radio Selection Change");
			}
		};
										



Rating

A **rating** component is an interactive UI element that allows users to provide feedback or evaluate content by selecting a value, typically represented by stars, hearts, or other icons. Ratings usually range on a scale (e.g., 1 to 5), visually indicating the level of satisfaction, quality, or preference. This component is commonly used in reviews, product feedback, surveys, and media platforms to capture user opinions quickly and intuitively. Ratings often support half or partial selections, hover effects, and can be displayed in both read-only and editable modes. They help guide other users’ decisions and provide valuable insights to content creators or service providers.

Rating component
		class RatingDemo : public GridPanel
		{
			Label _serviceRatingLabel;
			Rating _serviceRating;
			Label _issueResolvedRatingLabel;
			Rating _issueResolvedRating;
			Label _satisficationRatingLabel;
			Rating _satisficationRating;

		public:

			RatingDemo()
			{
				_serviceRatingLabel.setText(L"How did you feel about the service?");
				addComponent(&_serviceRatingLabel, 0, 0);
				addComponent(&_serviceRating, 0, 1);

				_issueResolvedRatingLabel.setText(L"Was the issue resolved?");
				addComponent(&_issueResolvedRatingLabel, 0, 3);
				addComponent(&_issueResolvedRating, 0, 4);

				_satisficationRatingLabel.setText(L"How do you rate your satisfaction with the service call?");
				addComponent(&_satisficationRatingLabel, 0, 6);
				addComponent(&_satisficationRating, 0, 7);

				setLayout({ -1 }, { 30, 30, 30, 30, 30, 30, 30, 30, -1 });
			}

			~RatingDemo()
			{
			}
		};
										



Slider

A **slider** is an interactive user interface component that lets users select a value or range by dragging a handle along a horizontal or vertical track. It provides a smooth and intuitive way to adjust numeric or continuous settings such as volume, brightness, price ranges, or timeline scrubbing. Sliders often display the current value dynamically as users move the handle, and can support single values or dual handles for selecting ranges. They enhance user experience by offering precise control in a compact and visually engaging format, commonly used in media players, settings panels, and data filters.

Slider Component
		class SliderDemo : public GridPanel, public SelectionChangeListener
		{
			Label _label1, _label2;
			Slider _slider1;
			Slider _slider2;
			Label _slider1CurrentValue, _slider2CurrentValue;

		public:

			SliderDemo()
			{
				_label1.setAlignment(-1);
				_label1.setText(L"Slider 1 - range 0-100");
				_label2.setAlignment(-1);
				_label2.setText(L"Slider 2 - range 0-1000");

				_slider1.setRange(0, 100);
				_slider1.addSelectionChangedListener(this);
				_slider2.setRange(0, 1000);
				_slider2.addSelectionChangedListener(this);

				_slider1CurrentValue.setText(L"Value = 0");
				_slider2CurrentValue.setText(L"Value = 0");

				setLayout({ -1 }, { 30,30,30,30,30,30, -1 });
				addComponent(&_label1, 0, 0);
				addComponent(&_slider1, 0, 1);
				addComponent(&_slider1CurrentValue, 0, 2);
				addComponent(&_label2, 0, 3);
				addComponent(&_slider2, 0, 4);
				addComponent(&_slider2CurrentValue, 0, 5);
			}

			~SliderDemo()
			{
			}

			void onSelectionChanged(const SelectionChangeEvent& ev)
			{
				if(ev.sourceComponentId == _slider1.getId())
					_slider1CurrentValue.setText(L"Value = "+ev.selectionValue);
				if (ev.sourceComponentId == _slider2.getId())
					_slider2CurrentValue.setText(L"Value = " + ev.selectionValue);


			}
		};
										



Switch

A **switch** is a toggle-style user interface component that allows users to quickly turn a setting or option on or off. Visually resembling a physical switch or slider, it typically slides or flips between two states—often labeled as “On” and “Off” or represented by different colors or icons. Switches are commonly used for enabling or disabling features like notifications, privacy settings, or connectivity options. They provide a clear, immediate way to change binary states, improving usability by making the current status obvious and interactions effortless. Switch components are designed to be accessible, responsive, and easy to understand at a glance.

Switch Component
		class SwitchDemo : public GridPanel, public SelectionChangeListener
		{
			Switch _switch;

		public:

			SwitchDemo()
			{
				_switch.setOptions(L"Male", L"Female");
				_switch.addSelectionChangedListener(this);

				setLayout({ -1 }, { 30, -1 });
				addComponent(&_switch, 0, 0);
			}

			~SwitchDemo()
			{
			}

			void onSelectionChanged(const SelectionChangeEvent& ev)
			{
				DialogFactory::showInfo(this, ev.selectionValue, L"Switch Selection Change");
			}
		};
										



Tabbed Pane

A **tabbed pane** is a user interface component that organizes content into multiple sections, each accessible through labeled tabs arranged typically at the top or side of the pane. Only one tab’s content is visible at a time, allowing users to switch between different views or categories without navigating away from the current screen. Tabbed panes help manage complex or related information in a compact space, improving navigation and reducing clutter. Commonly used in settings panels, dashboards, and multi-section forms, they provide a clear structure and easy access to different content areas while maintaining context. Well-designed tabbed panes support keyboard navigation and accessibility for a seamless user experience.

Tab Pane Component
		class TabPaneDemo : public GridPanel
		{
			TabPane _tabPane;

			ButtonDemo _buttonDemo;
			ButtonGridDemo _buttonGridDemo;
			ButtonMenuDemo _buttonMenuDemo;
			TreeViewDemo _treeViewDemo;

		public:

			TabPaneDemo()
			{
				_tabPane.addTab(L"Tree View", &_treeViewDemo);
				_tabPane.addTab(L"Buttons", &_buttonDemo);
				_tabPane.addTab(L"Button Grid", &_buttonGridDemo);
				_tabPane.addTab(L"Button Menu", &_buttonMenuDemo);

				setMargin(0);
				setLayout({ -1 }, { -1 });
				addComponent(&_tabPane, 0, 0);
			}

			~TabPaneDemo()
			{
			}
		};
										



TextArea

A **text area** is a user interface component that provides a larger, multi-line input field where users can enter, edit, and review extended blocks of text. Unlike a single-line text input, text areas are ideal for capturing longer responses such as comments, descriptions, messages, or feedback. Text areas often include features like resizing, scrollbars, and placeholder text to guide user input. They can support rich text formatting or plain text depending on the application. By offering ample space for detailed input, text areas enhance usability in forms, chat interfaces, and content creation tools.

TextArea Component
		class TextAreaDemo : public GridPanel, public ActionListener
		{
			Label _textAreaLabel;
			TextArea _textArea;

			Button _getTextButton, _getSelectedTextButton, _getLinesButton;

		public:

			TextAreaDemo()
			{
				_getTextButton.setText(L"getText");
				_getTextButton.addActionListener(this);
				_getSelectedTextButton.setText(L"getSelectedText");
				_getSelectedTextButton.addActionListener(this);
				_getLinesButton.setText(L"getLines");
				_getLinesButton.addActionListener(this);

				_textAreaLabel.setText(L"TextArea");
				addComponent(&_textAreaLabel, 0, 0, 3);
				addComponent(&_textArea, 0, 1, 3);

				addComponent(&_getTextButton, 0, 3);
				addComponent(&_getSelectedTextButton, 1, 3);
				addComponent(&_getLinesButton, 2, 3);

				setLayout({ -1, -1, -1 }, { 30, 100, 10, 30, -1 });
			}

			~TextAreaDemo()
			{
			}

			void onAction(const ActionEvent& ev)
			{
				if (ev.actionName == L"getText") {
					DialogFactory::showInfo(this, _textArea.getText());
				} else if (ev.actionName == L"getSelectedText") {
					DialogFactory::showInfo(this, _textArea.getSelectedText());
				} else if (ev.actionName == L"getLines") {
					vector lines;
					_textArea.getLines(lines);
					wstring combinedText = L"";
					for (size_t i = 0; i < lines.size(); i++) {
						combinedText += lines[i];
						combinedText += L"\n";
					}
					DialogFactory::showInfo(this, combinedText);
				}
			}
		};
										



TextField

A **text field** is a fundamental user interface component that allows users to enter and edit a single line of text. It’s commonly used in forms and applications for inputting data such as names, email addresses, passwords, or search queries. Text fields usually include features like placeholder text, input validation, and support for keyboard input. They may also offer options for masking input (e.g., for passwords), auto-completion, and clear buttons to enhance user experience. Simple and intuitive, text fields are essential for capturing user information efficiently and accurately.

TextField Component
		class TextFieldDemo : public GridPanel, public ActionListener
		{
			Label _textFieldLabel;
			TextField _textField;
			Label _passwordLabel;
			TextField _password;

			Button _getTextButton, _getSelectedTextButton;

		public:

			TextFieldDemo()
			{
				_getTextButton.setText(L"getText");
				_getTextButton.addActionListener(this);
				_getSelectedTextButton.setText(L"getSelectedText");
				_getSelectedTextButton.addActionListener(this);

				_textFieldLabel.setText(L"TextField");
				addComponent(&_textFieldLabel, 0, 0, 2);
				addComponent(&_textField, 0, 1, 2);

				addComponent(&_getTextButton, 0, 2);
				addComponent(&_getSelectedTextButton, 1, 2);

				_passwordLabel.setText(L"TextField.setPassword(TRUE)");
				addComponent(&_passwordLabel, 0, 4, 2);
				_password.setPassword(TRUE);
				addComponent(&_password, 0, 5, 2);

				setLayout({ -1, -1 }, { 30, 30, 30,30, 30, 30, -1 });
			}

			~TextFieldDemo()
			{
			}

			void onAction(const ActionEvent& ev)
			{
				if (ev.actionName == L"getText") {
					DialogFactory::showInfo(this, _textField.getText());
				}
				else if (ev.actionName == L"getSelectedText") {
					DialogFactory::showInfo(this, _textField.getSelectedText());
				}
			}
		};
										



ToastFactory

A **ToastFactory** is a utility or design pattern used in software development to create and manage toast notifications—small, temporary messages that appear on the screen to provide feedback or alerts without interrupting the user’s workflow. The ToastFactory centralizes the creation of toast messages, ensuring consistency in styling, behavior, duration, and placement across an application. Instead of manually building each toast notification, developers can use the factory to quickly generate toasts by specifying parameters like message text, type (success, error, info), and display duration. This approach promotes reusable, maintainable code and a unified user experience.

										
ToastFactory Class



ToggleButton (ButtonSelector)

A **button selector** is a UI component that presents a group of buttons where only one button can be selected at a time, allowing users to choose one option from several. It functions similarly to radio buttons but uses visually styled buttons to enhance interaction and clarity. Button selectors are commonly used for filtering, mode switching, or setting preferences—like selecting text alignment, view modes (grid/list), or payment options. The selected button is usually highlighted to clearly indicate the current choice, making the interface more intuitive and engaging.

ToggleButton Component
		class ToggleButtonDemo : public GridPanel
		{
			ToggleButton _maleFemale;
			ToggleButton _employmentStatus;

		public:

			ToggleButtonDemo()
			{
				_maleFemale.setOptions({ L"Male", L"Female" });
				_employmentStatus.setOptions({ L"Employed", L"Student", L"Retired"});

				setLayout({ -1 }, { 30, 30, 30, -1 });
				addComponent(&_maleFemale, 0, 0);
				addComponent(&_employmentStatus, 0, 2);
			}

			~ToggleButtonDemo()
			{
			}
		};
										



Tooltip

A **tooltip** is a small, informative popup that appears when a user hovers over, focuses on, or taps an element in a user interface. It provides additional context, explanations, or helpful hints about the element without cluttering the main UI. Tooltips are commonly used to clarify icons, buttons, form fields, or other controls—especially when their purpose might not be immediately obvious. They typically display concise text, appear near the target element, and disappear when the user moves away. Well-designed tooltips improve usability and accessibility by offering guidance just when it’s needed, enhancing the overall user experience.

										
Tooltip Component



Toolbar

A **buttons/icons toolbar** is a horizontal or vertical interface component that groups a collection of clickable buttons or icons, providing quick access to commonly used actions or tools within an application. Each button or icon represents a specific function—like formatting options, navigation controls, or commands—allowing users to perform tasks efficiently without navigating through menus. Toolbars are often customizable, support tooltips for clarity, and may include separators or grouping to organize related actions. They enhance productivity by keeping important features readily accessible, and their compact design helps maintain a clean and intuitive interface across desktop and mobile environments

Toolbar Component
		class ToolbarDemo : public GridPanel, public ActionListener
		{
			Toolbar _toolbar;

		public:

			ToolbarDemo()
			{
				_toolbar.addItem(1, L"Button-1", IconSource(L"logo.png"));
				_toolbar.addItem(2, L"", IconSource(L"logo.png"));
				_toolbar.addItem(3, L"Disabled", IconSource(L"logo.png"));
				_toolbar.addItem(4, L"Button-4", IconSource(L"logo.png"));
				_toolbar.addItem(5, L"Button-5", IconSource(L"logo.png"));
				_toolbar.addItem(6, L"Disabled", IconSource(L"logo.png"));
				_toolbar.addItem(7, L"Button-7", IconSource(L"logo.png"));
				_toolbar.addItem(8, L"Button-8", IconSource(L"logo.png"));
				_toolbar.addItem(9, L"Button-9", IconSource(L"logo.png"));
				_toolbar.addItem(10, L"Button-10", IconSource(L"logo.png"));
				_toolbar.addActionListener(this);

				_toolbar.enableItem(3, FALSE);
				_toolbar.enableItem(6, FALSE);

				setLayout({ -1 }, { 40, -1 });
				addComponent(&_toolbar, 0, 0);
			}

			~ToolbarDemo()
			{
			}

			void onAction(const ActionEvent& ev)
			{
				DialogFactory::showInfo(this, ev.actionName, L"Toolbar action");
			}
		};
										



Treeview

A **treeview** is a hierarchical user interface component that displays data or items in a nested, expandable list structure resembling a tree. Each item, or “node,” can have child nodes, allowing users to drill down into multiple levels of information by expanding or collapsing branches. Treeviews are commonly used for navigating file systems, organizational charts, menus, or any data that has parent-child relationships. They help users explore complex structures in a clear, organized way, making it easier to find and manage information without overwhelming the screen. Good treeviews support keyboard navigation, dynamic loading, and accessibility to enhance usability.

Tree Component
		class TreeViewDemo : public GridPanel, public SelectionChangeListener
		{
			TreeView _treeView;

		public:

			TreeViewDemo()
			{
				_treeView.clear();
				_treeView.setTitle(L"TreeView");

				_treeView.addItem(L"C:", L"C:");
				_treeView.addItem(L"Users", L"Users", L"C:");
				_treeView.addItem(L"John Doe", L"John Doe", L"Users");
				_treeView.addItem(L"Documents", L"Documents", L"John Doe");
				_treeView.addItem(L"Program Files", L"Program Files", L"C:");
				_treeView.addItem(L"Windows", L"Windows", L"C:");
				wchar_t id[100];
				for (long i = 1; i < 100; i++)
				{
					_ltow_s(i, id, 100, 10);
					_treeView.addItem(id, id, L"C:");
				}

				setMargin(0);
				setLayout({ -1 }, { -1 });
				addComponent(&_treeView, 0, 0);
			}

			~TreeViewDemo()
			{
			}

			void onSelectionChanged(const SelectionChangeEvent& ev)
			{
			//    DialogFactory::showInfo(getWindowHandle(), ev.selectionValue, L"Item Selected");
			}
		};