|
@@ -0,0 +1,1305 @@
|
|
|
|
|
+/*
|
|
|
|
|
+Blendish - Blender 2.5 UI based theming functions for NanoVG
|
|
|
|
|
+
|
|
|
|
|
+Copyright (c) 2014 Leonard Ritter <[email protected]>
|
|
|
|
|
+
|
|
|
|
|
+Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
+of this software and associated documentation files (the "Software"), to deal
|
|
|
|
|
+in the Software without restriction, including without limitation the rights
|
|
|
|
|
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
+copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
+furnished to do so, subject to the following conditions:
|
|
|
|
|
+
|
|
|
|
|
+The above copyright notice and this permission notice shall be included in
|
|
|
|
|
+all copies or substantial portions of the Software.
|
|
|
|
|
+
|
|
|
|
|
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
|
+THE SOFTWARE.
|
|
|
|
|
+*/
|
|
|
|
|
+
|
|
|
|
|
+#ifndef BLENDISH_H
|
|
|
|
|
+#define BLENDISH_H
|
|
|
|
|
+
|
|
|
|
|
+#ifndef NANOVG_H
|
|
|
|
|
+#error "nanovg.h must be included first."
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+#define fmaxf bx::fmax
|
|
|
|
|
+#define fminf bx::fmin
|
|
|
|
|
+
|
|
|
|
|
+#ifdef __cplusplus
|
|
|
|
|
+extern "C" {
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+/*
|
|
|
|
|
+
|
|
|
|
|
+Revision 3 (2014-07-08)
|
|
|
|
|
+
|
|
|
|
|
+Summary
|
|
|
|
|
+-------
|
|
|
|
|
+
|
|
|
|
|
+Blendish is a small collection of drawing functions for NanoVG, designed to
|
|
|
|
|
+replicate the look of the Blender 2.5+ User Interface. You can use these
|
|
|
|
|
+functions to theme your UI library. Several metric constants for faithful
|
|
|
|
|
+reproduction are also included.
|
|
|
|
|
+
|
|
|
|
|
+Blendish supports the original Blender icon sheet; As the licensing of Blenders
|
|
|
|
|
+icons is unclear, they are not included in Blendishes repository, but a SVG
|
|
|
|
|
+template, "icons_template.svg" is provided, which you can use to build your own
|
|
|
|
|
+icon sheet.
|
|
|
|
|
+
|
|
|
|
|
+To use icons, you must first load the icon sheet using one of the
|
|
|
|
|
+nvgCreateImage*() functions and then pass the image handle to bndSetIconImage();
|
|
|
|
|
+otherwise, no icons will be drawn. See bndSetIconImage() for more information.
|
|
|
|
|
+
|
|
|
|
|
+Blendish will not render text until a suitable UI font has been passed to
|
|
|
|
|
+bndSetFont() has been called. See bndSetFont() for more information.
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+Drawbacks
|
|
|
|
|
+---------
|
|
|
|
|
+
|
|
|
|
|
+There is no support varying dpi resolutions yet. The library is hardcoded
|
|
|
|
|
+to the equivalent of 72 dpi in the Blender system settings.
|
|
|
|
|
+
|
|
|
|
|
+Support for label truncation is missing. Text rendering breaks when widgets are
|
|
|
|
|
+too short to contain their labels.
|
|
|
|
|
+
|
|
|
|
|
+Usage
|
|
|
|
|
+-----
|
|
|
|
|
+
|
|
|
|
|
+To use this header file in implementation mode, define BLENDISH_IMPLEMENTATION
|
|
|
|
|
+before including blendish.h, otherwise the file will be in header-only mode.
|
|
|
|
|
+
|
|
|
|
|
+*/
|
|
|
|
|
+
|
|
|
|
|
+// if that typedef is provided elsewhere, you may define
|
|
|
|
|
+// BLENDISH_NO_NVG_TYPEDEFS before including the header.
|
|
|
|
|
+#ifndef BLENDISH_NO_NVG_TYPEDEFS
|
|
|
|
|
+typedef struct NVGcontext NVGcontext;
|
|
|
|
|
+typedef struct NVGcolor NVGcolor;
|
|
|
|
|
+typedef struct NVGglyphPosition NVGglyphPosition;
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+// describes the theme used to draw a single widget or widget box;
|
|
|
|
|
+// these values correspond to the same values that can be retrieved from
|
|
|
|
|
+// the Theme panel in the Blender preferences
|
|
|
|
|
+typedef struct BNDwidgetTheme {
|
|
|
|
|
+ // color of widget box outline
|
|
|
|
|
+ NVGcolor outlineColor;
|
|
|
|
|
+ // color of widget item (meaning changes depending on class)
|
|
|
|
|
+ NVGcolor itemColor;
|
|
|
|
|
+ // fill color of widget box
|
|
|
|
|
+ NVGcolor innerColor;
|
|
|
|
|
+ // fill color of widget box when active
|
|
|
|
|
+ NVGcolor innerSelectedColor;
|
|
|
|
|
+ // color of text label
|
|
|
|
|
+ NVGcolor textColor;
|
|
|
|
|
+ // color of text label when active
|
|
|
|
|
+ NVGcolor textSelectedColor;
|
|
|
|
|
+ // delta modifier for upper part of gradient (-100 to 100)
|
|
|
|
|
+ int shadeTop;
|
|
|
|
|
+ // delta modifier for lower part of gradient (-100 to 100)
|
|
|
|
|
+ int shadeDown;
|
|
|
|
|
+} BNDwidgetTheme;
|
|
|
|
|
+
|
|
|
|
|
+// describes the theme used to draw widgets
|
|
|
|
|
+typedef struct BNDtheme {
|
|
|
|
|
+ // the background color of panels and windows
|
|
|
|
|
+ NVGcolor backgroundColor;
|
|
|
|
|
+ // theme for labels
|
|
|
|
|
+ BNDwidgetTheme regularTheme;
|
|
|
|
|
+ // theme for tool buttons
|
|
|
|
|
+ BNDwidgetTheme toolTheme;
|
|
|
|
|
+ // theme for radio buttons
|
|
|
|
|
+ BNDwidgetTheme radioTheme;
|
|
|
|
|
+ // theme for text fields
|
|
|
|
|
+ BNDwidgetTheme textFieldTheme;
|
|
|
|
|
+ // theme for option buttons (checkboxes)
|
|
|
|
|
+ BNDwidgetTheme optionTheme;
|
|
|
|
|
+ // theme for choice buttons (comboboxes)
|
|
|
|
|
+ // Blender calls them "menu buttons"
|
|
|
|
|
+ BNDwidgetTheme choiceTheme;
|
|
|
|
|
+ // theme for number fields
|
|
|
|
|
+ BNDwidgetTheme numberFieldTheme;
|
|
|
|
|
+ // theme for slider controls
|
|
|
|
|
+ BNDwidgetTheme sliderTheme;
|
|
|
|
|
+ // theme for scrollbars
|
|
|
|
|
+ BNDwidgetTheme scrollBarTheme;
|
|
|
|
|
+ // theme for tooltips
|
|
|
|
|
+ BNDwidgetTheme tooltipTheme;
|
|
|
|
|
+ // theme for menu backgrounds
|
|
|
|
|
+ BNDwidgetTheme menuTheme;
|
|
|
|
|
+ // theme for menu items
|
|
|
|
|
+ BNDwidgetTheme menuItemTheme;
|
|
|
|
|
+} BNDtheme;
|
|
|
|
|
+
|
|
|
|
|
+// how text on a control is aligned
|
|
|
|
|
+typedef enum BNDtextAlignment {
|
|
|
|
|
+ BND_LEFT = 0,
|
|
|
|
|
+ BND_CENTER,
|
|
|
|
|
+} BNDtextAlignment;
|
|
|
|
|
+
|
|
|
|
|
+// states altering the styling of a widget
|
|
|
|
|
+typedef enum BNDwidgetState {
|
|
|
|
|
+ // not interacting
|
|
|
|
|
+ BND_DEFAULT = 0,
|
|
|
|
|
+ // the mouse is hovering over the control
|
|
|
|
|
+ BND_HOVER,
|
|
|
|
|
+ // the widget is activated (pressed) or in an active state (toggled)
|
|
|
|
|
+ BND_ACTIVE
|
|
|
|
|
+} BNDwidgetState;
|
|
|
|
|
+
|
|
|
|
|
+// flags indicating which corners are sharp (for grouping widgets)
|
|
|
|
|
+typedef enum BNDcornerFlags {
|
|
|
|
|
+ // all corners are round
|
|
|
|
|
+ BND_CORNER_NONE = 0,
|
|
|
|
|
+ // sharp top left corner
|
|
|
|
|
+ BND_CORNER_TOP_LEFT = 1,
|
|
|
|
|
+ // sharp top right corner
|
|
|
|
|
+ BND_CORNER_TOP_RIGHT = 2,
|
|
|
|
|
+ // sharp bottom right corner
|
|
|
|
|
+ BND_CORNER_DOWN_RIGHT = 4,
|
|
|
|
|
+ // sharp bottom left corner
|
|
|
|
|
+ BND_CORNER_DOWN_LEFT = 8,
|
|
|
|
|
+ // all corners are sharp;
|
|
|
|
|
+ // you can invert a set of flags using ^= BND_CORNER_ALL
|
|
|
|
|
+ BND_CORNER_ALL = 0xF,
|
|
|
|
|
+ // top border is sharp
|
|
|
|
|
+ BND_CORNER_TOP = 3,
|
|
|
|
|
+ // bottom border is sharp
|
|
|
|
|
+ BND_CORNER_DOWN = 0xC,
|
|
|
|
|
+ // left border is sharp
|
|
|
|
|
+ BND_CORNER_LEFT = 9,
|
|
|
|
|
+ // right border is sharp
|
|
|
|
|
+ BND_CORNER_RIGHT = 6
|
|
|
|
|
+} BNDcornerFlags;
|
|
|
|
|
+
|
|
|
|
|
+// build an icon ID from two coordinates into the icon sheet, where
|
|
|
|
|
+// (0,0) designates the upper-leftmost icon, (1,0) the one right next to it,
|
|
|
|
|
+// and so on.
|
|
|
|
|
+#define BND_ICONID(x,y) ((x)|((y)<<8))
|
|
|
|
|
+
|
|
|
|
|
+// default widget height
|
|
|
|
|
+#define BND_WIDGET_HEIGHT 21
|
|
|
|
|
+// default toolbutton width (if icon only)
|
|
|
|
|
+#define BND_TOOL_WIDTH 20
|
|
|
|
|
+
|
|
|
|
|
+// width of vertical scrollbar
|
|
|
|
|
+#define BND_SCROLLBAR_WIDTH 13
|
|
|
|
|
+// height of horizontal scrollbar
|
|
|
|
|
+#define BND_SCROLLBAR_HEIGHT 14
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
+
|
|
|
|
|
+// set the current theme all widgets will be drawn with.
|
|
|
|
|
+// the default Blender 2.6 theme is set by default.
|
|
|
|
|
+void bndSetTheme(BNDtheme theme);
|
|
|
|
|
+
|
|
|
|
|
+// Returns the currently set theme
|
|
|
|
|
+const BNDtheme *bndGetTheme();
|
|
|
|
|
+
|
|
|
|
|
+// designates an image handle as returned by nvgCreateImage*() as the themes'
|
|
|
|
|
+// icon sheet. The icon sheet format must be compatible to Blender 2.6's icon
|
|
|
|
|
+// sheet; the order of icons does not matter.
|
|
|
|
|
+// A valid icon sheet is e.g. shown at
|
|
|
|
|
+// http://wiki.blender.org/index.php/Dev:2.5/Doc/How_to/Add_an_icon
|
|
|
|
|
+void bndSetIconImage(int image);
|
|
|
|
|
+
|
|
|
|
|
+// designates an image handle as returned by nvgCreateFont*() as the themes'
|
|
|
|
|
+// UI font. Blender's original UI font Droid Sans is perfectly suited and
|
|
|
|
|
+// available here:
|
|
|
|
|
+// https://svn.blender.org/svnroot/bf-blender/trunk/blender/release/datafiles/fonts/
|
|
|
|
|
+void bndSetFont(int font);
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
+
|
|
|
|
|
+// High Level Functions
|
|
|
|
|
+// --------------------
|
|
|
|
|
+// Use these functions to draw themed widgets with your NVGcontext.
|
|
|
|
|
+
|
|
|
|
|
+// Draw a label with its lower left origin at (x,y) and size of (w,h).
|
|
|
|
|
+// if iconid >= 0, an icon will be added to the widget
|
|
|
|
|
+// if label is not NULL, a label will be added to the widget
|
|
|
|
|
+// widget looks best when height is BND_WIDGET_HEIGHT
|
|
|
|
|
+void bndLabel(NVGcontext *ctx,
|
|
|
|
|
+ float x, float y, float w, float h, int iconid, const char *label);
|
|
|
|
|
+
|
|
|
|
|
+// Draw a tool button with its lower left origin at (x,y) and size of (w,h),
|
|
|
|
|
+// where flags is one or multiple flags from BNDcornerFlags and state denotes
|
|
|
|
|
+// the widgets current UI state.
|
|
|
|
|
+// if iconid >= 0, an icon will be added to the widget
|
|
|
|
|
+// if label is not NULL, a label will be added to the widget
|
|
|
|
|
+// widget looks best when height is BND_WIDGET_HEIGHT
|
|
|
|
|
+void bndToolButton(NVGcontext *ctx,
|
|
|
|
|
+ float x, float y, float w, float h, int flags, BNDwidgetState state,
|
|
|
|
|
+ int iconid, const char *label);
|
|
|
|
|
+
|
|
|
|
|
+// Draw a radio button with its lower left origin at (x,y) and size of (w,h),
|
|
|
|
|
+// where flags is one or multiple flags from BNDcornerFlags and state denotes
|
|
|
|
|
+// the widgets current UI state.
|
|
|
|
|
+// if iconid >= 0, an icon will be added to the widget
|
|
|
|
|
+// if label is not NULL, a label will be added to the widget
|
|
|
|
|
+// widget looks best when height is BND_WIDGET_HEIGHT
|
|
|
|
|
+void bndRadioButton(NVGcontext *ctx,
|
|
|
|
|
+ float x, float y, float w, float h, int flags, BNDwidgetState state,
|
|
|
|
|
+ int iconid, const char *label);
|
|
|
|
|
+
|
|
|
|
|
+// Draw a text field with its lower left origin at (x,y) and size of (w,h),
|
|
|
|
|
+// where flags is one or multiple flags from BNDcornerFlags and state denotes
|
|
|
|
|
+// the widgets current UI state.
|
|
|
|
|
+// if iconid >= 0, an icon will be added to the widget
|
|
|
|
|
+// if text is not NULL, text will be printed to the widget
|
|
|
|
|
+// cbegin must be >= 0 and <= strlen(text) and denotes the beginning of the caret
|
|
|
|
|
+// cend must be >= cbegin and <= strlen(text) and denotes the end of the caret
|
|
|
|
|
+// if cend < cbegin, then no caret will be drawn
|
|
|
|
|
+// widget looks best when height is BND_WIDGET_HEIGHT
|
|
|
|
|
+void bndTextField(NVGcontext *ctx,
|
|
|
|
|
+ float x, float y, float w, float h, int flags, BNDwidgetState state,
|
|
|
|
|
+ int iconid, const char *text, int cbegin, int cend);
|
|
|
|
|
+
|
|
|
|
|
+// Draw an option button with its lower left origin at (x,y) and size of (w,h),
|
|
|
|
|
+// where flags is one or multiple flags from BNDcornerFlags and state denotes
|
|
|
|
|
+// the widgets current UI state.
|
|
|
|
|
+// if label is not NULL, a label will be added to the widget
|
|
|
|
|
+// widget looks best when height is BND_WIDGET_HEIGHT
|
|
|
|
|
+void bndOptionButton(NVGcontext *ctx,
|
|
|
|
|
+ float x, float y, float w, float h, BNDwidgetState state,
|
|
|
|
|
+ const char *label);
|
|
|
|
|
+
|
|
|
|
|
+// Draw a choice button with its lower left origin at (x,y) and size of (w,h),
|
|
|
|
|
+// where flags is one or multiple flags from BNDcornerFlags and state denotes
|
|
|
|
|
+// the widgets current UI state.
|
|
|
|
|
+// if iconid >= 0, an icon will be added to the widget
|
|
|
|
|
+// if label is not NULL, a label will be added to the widget
|
|
|
|
|
+// widget looks best when height is BND_WIDGET_HEIGHT
|
|
|
|
|
+void bndChoiceButton(NVGcontext *ctx,
|
|
|
|
|
+ float x, float y, float w, float h, int flags, BNDwidgetState state,
|
|
|
|
|
+ int iconid, const char *label);
|
|
|
|
|
+
|
|
|
|
|
+// Draw a number field with its lower left origin at (x,y) and size of (w,h),
|
|
|
|
|
+// where flags is one or multiple flags from BNDcornerFlags and state denotes
|
|
|
|
|
+// the widgets current UI state.
|
|
|
|
|
+// if label is not NULL, a label will be added to the widget
|
|
|
|
|
+// if value is not NULL, a value will be added to the widget, along with
|
|
|
|
|
+// a ":" separator
|
|
|
|
|
+// widget looks best when height is BND_WIDGET_HEIGHT
|
|
|
|
|
+void bndNumberField(NVGcontext *ctx,
|
|
|
|
|
+ float x, float y, float w, float h, int flags, BNDwidgetState state,
|
|
|
|
|
+ const char *label, const char *value);
|
|
|
|
|
+
|
|
|
|
|
+// Draw slider control with its lower left origin at (x,y) and size of (w,h),
|
|
|
|
|
+// where flags is one or multiple flags from BNDcornerFlags and state denotes
|
|
|
|
|
+// the widgets current UI state.
|
|
|
|
|
+// progress must be in the range 0..1 and controls the size of the slider bar
|
|
|
|
|
+// if label is not NULL, a label will be added to the widget
|
|
|
|
|
+// if value is not NULL, a value will be added to the widget, along with
|
|
|
|
|
+// a ":" separator
|
|
|
|
|
+// widget looks best when height is BND_WIDGET_HEIGHT
|
|
|
|
|
+void bndSlider(NVGcontext *ctx,
|
|
|
|
|
+ float x, float y, float w, float h, int flags, BNDwidgetState state,
|
|
|
|
|
+ float progress, const char *label, const char *value);
|
|
|
|
|
+
|
|
|
|
|
+// Draw scrollbar with its lower left origin at (x,y) and size of (w,h),
|
|
|
|
|
+// where state denotes the widgets current UI state.
|
|
|
|
|
+// offset is in the range 0..1 and controls the position of the scroll handle
|
|
|
|
|
+// size is in the range 0..1 and controls the size of the scroll handle
|
|
|
|
|
+// horizontal widget looks best when height is BND_SCROLLBAR_HEIGHT,
|
|
|
|
|
+// vertical looks best when width is BND_SCROLLBAR_WIDTH
|
|
|
|
|
+void bndScrollBar(NVGcontext *ctx,
|
|
|
|
|
+ float x, float y, float w, float h, BNDwidgetState state,
|
|
|
|
|
+ float offset, float size);
|
|
|
|
|
+
|
|
|
|
|
+// Draw a menu background with its lower left origin at (x,y) and size of (w,h),
|
|
|
|
|
+// where flags is one or multiple flags from BNDcornerFlags.
|
|
|
|
|
+void bndMenuBackground(NVGcontext *ctx,
|
|
|
|
|
+ float x, float y, float w, float h, int flags);
|
|
|
|
|
+
|
|
|
|
|
+// Draw a menu label with its lower left origin at (x,y) and size of (w,h).
|
|
|
|
|
+// if iconid >= 0, an icon will be added to the widget
|
|
|
|
|
+// if label is not NULL, a label will be added to the widget
|
|
|
|
|
+// widget looks best when height is BND_WIDGET_HEIGHT
|
|
|
|
|
+void bndMenuLabel(NVGcontext *ctx,
|
|
|
|
|
+ float x, float y, float w, float h, int iconid, const char *label);
|
|
|
|
|
+
|
|
|
|
|
+// Draw a menu item with its lower left origin at (x,y) and size of (w,h),
|
|
|
|
|
+// where state denotes the widgets current UI state.
|
|
|
|
|
+// if iconid >= 0, an icon will be added to the widget
|
|
|
|
|
+// if label is not NULL, a label will be added to the widget
|
|
|
|
|
+// widget looks best when height is BND_WIDGET_HEIGHT
|
|
|
|
|
+void bndMenuItem(NVGcontext *ctx,
|
|
|
|
|
+ float x, float y, float w, float h, BNDwidgetState state,
|
|
|
|
|
+ int iconid, const char *label);
|
|
|
|
|
+
|
|
|
|
|
+// Draw a tooltip background with its lower left origin at (x,y) and size of (w,h)
|
|
|
|
|
+void bndTooltipBackground(NVGcontext *ctx, float x, float y, float w, float h);
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
+
|
|
|
|
|
+// Low Level Functions
|
|
|
|
|
+// -------------------
|
|
|
|
|
+// these are part of the implementation detail and can be used to theme
|
|
|
|
|
+// new kinds of controls in a similar fashion.
|
|
|
|
|
+
|
|
|
|
|
+// make color transparent using the default alpha value
|
|
|
|
|
+NVGcolor bndTransparent(NVGcolor color);
|
|
|
|
|
+
|
|
|
|
|
+// offset a color by a given integer delta in the range -100 to 100
|
|
|
|
|
+NVGcolor bndOffsetColor(NVGcolor color, int delta);
|
|
|
|
|
+
|
|
|
|
|
+// assigns radius r to the four entries of array radiuses depending on whether
|
|
|
|
|
+// the corner is marked as sharp or not; see BNDcornerFlags for possible
|
|
|
|
|
+// flag values.
|
|
|
|
|
+void bndSelectCorners(float *radiuses, float r, int flags);
|
|
|
|
|
+
|
|
|
|
|
+// computes the upper and lower gradient colors for the inner box from a widget
|
|
|
|
|
+// theme and the widgets state. If flipActive is set and the state is
|
|
|
|
|
+// BND_ACTIVE, the upper and lower colors will be swapped.
|
|
|
|
|
+void bndInnerColors(NVGcolor *shade_top, NVGcolor *shade_down,
|
|
|
|
|
+ const BNDwidgetTheme *theme, BNDwidgetState state, int flipActive);
|
|
|
|
|
+
|
|
|
|
|
+// computes the text color for a widget label from a widget theme and the
|
|
|
|
|
+// widgets state.
|
|
|
|
|
+NVGcolor bndTextColor(const BNDwidgetTheme *theme, BNDwidgetState state);
|
|
|
|
|
+
|
|
|
|
|
+// computes the bounds of the scrollbar handle from the scrollbar size
|
|
|
|
|
+// and the handles offset and size.
|
|
|
|
|
+// offset is in the range 0..1 and defines the position of the scroll handle
|
|
|
|
|
+// size is in the range 0..1 and defines the size of the scroll handle
|
|
|
|
|
+void bndScrollHandleRect(float *x, float *y, float *w, float *h,
|
|
|
|
|
+ float offset, float size);
|
|
|
|
|
+
|
|
|
|
|
+// Add a rounded box path at position (x,y) with size (w,h) and a separate
|
|
|
|
|
+// radius for each corner listed in clockwise order, so that cr0 = top left,
|
|
|
|
|
+// cr1 = top right, cr2 = bottom right, cr3 = bottom left;
|
|
|
|
|
+// this is a low level drawing function: the path must be stroked or filled
|
|
|
|
|
+// to become visible.
|
|
|
|
|
+void bndRoundedBox(NVGcontext *ctx, float x, float y, float w, float h,
|
|
|
|
|
+ float cr0, float cr1, float cr2, float cr3);
|
|
|
|
|
+
|
|
|
|
|
+// Draw a flat panel without any decorations at position (x,y) with size (w,h)
|
|
|
|
|
+// and fills it with backgroundColor
|
|
|
|
|
+void bndBackground(NVGcontext *ctx, float x, float y, float w, float h);
|
|
|
|
|
+
|
|
|
|
|
+// Draw a lower inset for a rounded box at position (x,y) with size (w,h)
|
|
|
|
|
+// that gives the impression the surface has been pushed in.
|
|
|
|
|
+// cr2 and cr3 contain the radiuses of the bottom right and bottom left
|
|
|
|
|
+// corners of the rounded box.
|
|
|
|
|
+void bndBevelInset(NVGcontext *ctx, float x, float y, float w, float h,
|
|
|
|
|
+ float cr2, float cr3);
|
|
|
|
|
+
|
|
|
|
|
+// Draw an icon with (x,y) as its upper left coordinate; the iconid selects
|
|
|
|
|
+// the icon from the sheet; use the BND_ICONID macro to build icon IDs.
|
|
|
|
|
+void bndIcon(NVGcontext *ctx, float x, float y, int iconid);
|
|
|
|
|
+
|
|
|
|
|
+// Draw a drop shadow around the rounded box at (x,y) with size (w,h) and
|
|
|
|
|
+// radius r, with feather as its maximum range in pixels.
|
|
|
|
|
+// No shadow will be painted inside the rounded box.
|
|
|
|
|
+void bndDropShadow(NVGcontext *ctx, float x, float y, float w, float h,
|
|
|
|
|
+ float r, float feather, float alpha);
|
|
|
|
|
+
|
|
|
|
|
+// Draw the inner part of a widget box, with a gradient from shade_top to
|
|
|
|
|
+// shade_down. If h>w, the gradient will be horizontal instead of
|
|
|
|
|
+// vertical.
|
|
|
|
|
+void bndInnerBox(NVGcontext *ctx, float x, float y, float w, float h,
|
|
|
|
|
+ float cr0, float cr1, float cr2, float cr3,
|
|
|
|
|
+ NVGcolor shade_top, NVGcolor shade_down);
|
|
|
|
|
+
|
|
|
|
|
+// Draw the outline part of a widget box with the given color
|
|
|
|
|
+void bndOutlineBox(NVGcontext *ctx, float x, float y, float w, float h,
|
|
|
|
|
+ float cr0, float cr1, float cr2, float cr3, NVGcolor color);
|
|
|
|
|
+
|
|
|
|
|
+// Draw an optional icon specified by <iconid> and an optional label with
|
|
|
|
|
+// given alignment (BNDtextAlignment), fontsize and color within a widget box.
|
|
|
|
|
+// if iconid is >= 0, an icon will be drawn and the labels remaining space
|
|
|
|
|
+// will be adjusted.
|
|
|
|
|
+// if label is not NULL, it will be drawn with the specified alignment, fontsize
|
|
|
|
|
+// and color.
|
|
|
|
|
+// if value is not NULL, label and value will be drawn with a ":" separator
|
|
|
|
|
+// inbetween.
|
|
|
|
|
+void bndIconLabelValue(NVGcontext *ctx, float x, float y, float w, float h,
|
|
|
|
|
+ int iconid, NVGcolor color, int align, float fontsize, const char *label,
|
|
|
|
|
+ const char *value);
|
|
|
|
|
+
|
|
|
|
|
+// Draw an optional icon specified by <iconid>, an optional label and
|
|
|
|
|
+// a caret with given fontsize and color within a widget box.
|
|
|
|
|
+// if iconid is >= 0, an icon will be drawn and the labels remaining space
|
|
|
|
|
+// will be adjusted.
|
|
|
|
|
+// if label is not NULL, it will be drawn with the specified alignment, fontsize
|
|
|
|
|
+// and color.
|
|
|
|
|
+// cbegin must be >= 0 and <= strlen(text) and denotes the beginning of the caret
|
|
|
|
|
+// cend must be >= cbegin and <= strlen(text) and denotes the end of the caret
|
|
|
|
|
+// if cend < cbegin, then no caret will be drawn
|
|
|
|
|
+void bndIconLabelCaret(NVGcontext *ctx, float x, float y, float w, float h,
|
|
|
|
|
+ int iconid, NVGcolor color, float fontsize, const char *label,
|
|
|
|
|
+ NVGcolor caretcolor, int cbegin, int cend);
|
|
|
|
|
+
|
|
|
|
|
+// Draw a checkmark for an option box with the given upper left coordinates
|
|
|
|
|
+// (ox,oy) with the specified color.
|
|
|
|
|
+void bndCheck(NVGcontext *ctx, float ox, float oy, NVGcolor color);
|
|
|
|
|
+
|
|
|
|
|
+// Draw a horizontal arrow for a number field with its center at (x,y) and
|
|
|
|
|
+// size s; if s is negative, the arrow points to the left.
|
|
|
|
|
+void bndArrow(NVGcontext *ctx, float x, float y, float s, NVGcolor color);
|
|
|
|
|
+
|
|
|
|
|
+// Draw an up/down arrow for a choice box with its center at (x,y) and size s
|
|
|
|
|
+void bndUpDownArrow(NVGcontext *ctx, float x, float y, float s, NVGcolor color);
|
|
|
|
|
+
|
|
|
|
|
+#ifdef __cplusplus
|
|
|
|
|
+};
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+#endif // BLENDISH_H
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
+////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
+
|
|
|
|
|
+#ifdef BLENDISH_IMPLEMENTATION
|
|
|
|
|
+
|
|
|
|
|
+#include <memory.h>
|
|
|
|
|
+#include <math.h>
|
|
|
|
|
+
|
|
|
|
|
+#ifdef _MSC_VER
|
|
|
|
|
+ #pragma warning (disable: 4996) // Switch off security warnings
|
|
|
|
|
+ #pragma warning (disable: 4100) // Switch off unreferenced formal parameter warnings
|
|
|
|
|
+ #ifdef __cplusplus
|
|
|
|
|
+ #define BND_INLINE inline
|
|
|
|
|
+ #else
|
|
|
|
|
+ #define BND_INLINE
|
|
|
|
|
+ #endif
|
|
|
|
|
+#else
|
|
|
|
|
+ #define BND_INLINE inline
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
+
|
|
|
|
|
+// default text size
|
|
|
|
|
+#define BND_LABEL_FONT_SIZE 13
|
|
|
|
|
+
|
|
|
|
|
+// default text padding in inner box
|
|
|
|
|
+#define BND_PAD_LEFT 8
|
|
|
|
|
+#define BND_PAD_RIGHT 8
|
|
|
|
|
+
|
|
|
|
|
+// label: value separator string
|
|
|
|
|
+#define BND_LABEL_SEPARATOR ": "
|
|
|
|
|
+
|
|
|
|
|
+// alpha intensity of transparent items (0xa4)
|
|
|
|
|
+#define BND_TRANSPARENT_ALPHA 0.643
|
|
|
|
|
+
|
|
|
|
|
+// shade intensity of beveled insets
|
|
|
|
|
+#define BND_BEVEL_SHADE 30
|
|
|
|
|
+// shade intensity of hovered inner boxes
|
|
|
|
|
+#define BND_HOVER_SHADE 30
|
|
|
|
|
+
|
|
|
|
|
+// width of icon sheet
|
|
|
|
|
+#define BND_ICON_SHEET_WIDTH 602
|
|
|
|
|
+// height of icon sheet
|
|
|
|
|
+#define BND_ICON_SHEET_HEIGHT 640
|
|
|
|
|
+// gridsize of icon sheet in both dimensions
|
|
|
|
|
+#define BND_ICON_SHEET_GRID 21
|
|
|
|
|
+// offset of first icon tile relative to left border
|
|
|
|
|
+#define BND_ICON_SHEET_OFFSET_X 5
|
|
|
|
|
+// offset of first icon tile relative to top border
|
|
|
|
|
+#define BND_ICON_SHEET_OFFSET_Y 10
|
|
|
|
|
+// resolution of single icon
|
|
|
|
|
+#define BND_ICON_SHEET_RES 16
|
|
|
|
|
+
|
|
|
|
|
+// size of number field arrow
|
|
|
|
|
+#define BND_NUMBER_ARROW_SIZE 4
|
|
|
|
|
+
|
|
|
|
|
+// default text color
|
|
|
|
|
+#define BND_COLOR_TEXT {{{ 0,0,0,1 }}}
|
|
|
|
|
+// default highlighted text color
|
|
|
|
|
+#define BND_COLOR_TEXT_SELECTED {{{ 1,1,1,1 }}}
|
|
|
|
|
+
|
|
|
|
|
+// radius of tool button
|
|
|
|
|
+#define BND_TOOL_RADIUS 4
|
|
|
|
|
+
|
|
|
|
|
+// radius of option button
|
|
|
|
|
+#define BND_OPTION_RADIUS 4
|
|
|
|
|
+// width of option button checkbox
|
|
|
|
|
+#define BND_OPTION_WIDTH 14
|
|
|
|
|
+// height of option button checkbox
|
|
|
|
|
+#define BND_OPTION_HEIGHT 15
|
|
|
|
|
+
|
|
|
|
|
+// radius of text field
|
|
|
|
|
+#define BND_TEXT_RADIUS 4
|
|
|
|
|
+
|
|
|
|
|
+// radius of number button
|
|
|
|
|
+#define BND_NUMBER_RADIUS 10
|
|
|
|
|
+
|
|
|
|
|
+// radius of menu popup
|
|
|
|
|
+#define BND_MENU_RADIUS 3
|
|
|
|
|
+// feather of menu popup shadow
|
|
|
|
|
+#define BND_SHADOW_FEATHER 12
|
|
|
|
|
+// alpha of menu popup shadow
|
|
|
|
|
+#define BND_SHADOW_ALPHA 0.5
|
|
|
|
|
+
|
|
|
|
|
+// radius of scrollbar
|
|
|
|
|
+#define BND_SCROLLBAR_RADIUS 7
|
|
|
|
|
+// shade intensity of active scrollbar
|
|
|
|
|
+#define BND_SCROLLBAR_ACTIVE_SHADE 15
|
|
|
|
|
+
|
|
|
|
|
+// max glyphs for position testing
|
|
|
|
|
+#define BND_MAX_GLYPHS 1024
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
+
|
|
|
|
|
+BND_INLINE float bnd_clamp(float v, float mn, float mx) {
|
|
|
|
|
+ return (v > mx)?mx:(v < mn)?mn:v;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
+
|
|
|
|
|
+// the initial theme
|
|
|
|
|
+static BNDtheme bnd_theme = {
|
|
|
|
|
+ // backgroundColor
|
|
|
|
|
+ {{{ 0.447, 0.447, 0.447, 1.0 }}},
|
|
|
|
|
+ // regularTheme
|
|
|
|
|
+ {
|
|
|
|
|
+ {{{ 0.098,0.098,0.098,1 }}}, // color_outline
|
|
|
|
|
+ {{{ 0.098,0.098,0.098,1 }}}, // color_item
|
|
|
|
|
+ {{{ 0.6,0.6,0.6,1 }}}, // color_inner
|
|
|
|
|
+ {{{ 0.392,0.392,0.392,1 }}}, // color_inner_selected
|
|
|
|
|
+ BND_COLOR_TEXT, // color_text
|
|
|
|
|
+ BND_COLOR_TEXT_SELECTED, // color_text_selected
|
|
|
|
|
+ 0, // shade_top
|
|
|
|
|
+ 0, // shade_down
|
|
|
|
|
+ },
|
|
|
|
|
+ // toolTheme
|
|
|
|
|
+ {
|
|
|
|
|
+ {{{ 0.098,0.098,0.098,1 }}}, // color_outline
|
|
|
|
|
+ {{{ 0.098,0.098,0.098,1 }}}, // color_item
|
|
|
|
|
+ {{{ 0.6,0.6,0.6,1 }}}, // color_inner
|
|
|
|
|
+ {{{ 0.392,0.392,0.392,1 }}}, // color_inner_selected
|
|
|
|
|
+ BND_COLOR_TEXT, // color_text
|
|
|
|
|
+ BND_COLOR_TEXT_SELECTED, // color_text_selected
|
|
|
|
|
+ 15, // shade_top
|
|
|
|
|
+ -15, // shade_down
|
|
|
|
|
+ },
|
|
|
|
|
+ // radioTheme
|
|
|
|
|
+ {
|
|
|
|
|
+ {{{ 0,0,0,1 }}}, // color_outline
|
|
|
|
|
+ {{{ 1,1,1,1 }}}, // color_item
|
|
|
|
|
+ {{{ 0.275,0.275,0.275,1 }}}, // color_inner
|
|
|
|
|
+ {{{ 0.337,0.502,0.761,1 }}}, // color_inner_selected
|
|
|
|
|
+ BND_COLOR_TEXT_SELECTED, // color_text
|
|
|
|
|
+ BND_COLOR_TEXT, // color_text_selected
|
|
|
|
|
+ 15, // shade_top
|
|
|
|
|
+ -15, // shade_down
|
|
|
|
|
+ },
|
|
|
|
|
+ // textFieldTheme
|
|
|
|
|
+ {
|
|
|
|
|
+ {{{ 0.098,0.098,0.098,1 }}}, // color_outline
|
|
|
|
|
+ {{{ 0.353, 0.353, 0.353,1 }}}, // color_item
|
|
|
|
|
+ {{{ 0.6, 0.6, 0.6,1 }}}, // color_inner
|
|
|
|
|
+ {{{ 0.6, 0.6, 0.6,1 }}}, // color_inner_selected
|
|
|
|
|
+ BND_COLOR_TEXT, // color_text
|
|
|
|
|
+ BND_COLOR_TEXT_SELECTED, // color_text_selected
|
|
|
|
|
+ 0, // shade_top
|
|
|
|
|
+ 25, // shade_down
|
|
|
|
|
+ },
|
|
|
|
|
+ // optionTheme
|
|
|
|
|
+ {
|
|
|
|
|
+ {{{ 0,0,0,1 }}}, // color_outline
|
|
|
|
|
+ {{{ 1,1,1,1 }}}, // color_item
|
|
|
|
|
+ {{{ 0.275,0.275,0.275,1 }}}, // color_inner
|
|
|
|
|
+ {{{ 0.275,0.275,0.275,1 }}}, // color_inner_selected
|
|
|
|
|
+ BND_COLOR_TEXT, // color_text
|
|
|
|
|
+ BND_COLOR_TEXT_SELECTED, // color_text_selected
|
|
|
|
|
+ 15, // shade_top
|
|
|
|
|
+ -15, // shade_down
|
|
|
|
|
+ },
|
|
|
|
|
+ // choiceTheme
|
|
|
|
|
+ {
|
|
|
|
|
+ {{{ 0,0,0,1 }}}, // color_outline
|
|
|
|
|
+ {{{ 1,1,1,1 }}}, // color_item
|
|
|
|
|
+ {{{ 0.275,0.275,0.275,1 }}}, // color_inner
|
|
|
|
|
+ {{{ 0.275,0.275,0.275,1 }}}, // color_inner_selected
|
|
|
|
|
+ BND_COLOR_TEXT_SELECTED, // color_text
|
|
|
|
|
+ {{{ 0.8,0.8,0.8,1 }}}, // color_text_selected
|
|
|
|
|
+ 15, // shade_top
|
|
|
|
|
+ -15, // shade_down
|
|
|
|
|
+ },
|
|
|
|
|
+ // numberFieldTheme
|
|
|
|
|
+ {
|
|
|
|
|
+ {{{ 0.098,0.098,0.098,1 }}}, // color_outline
|
|
|
|
|
+ {{{ 0.353, 0.353, 0.353,1 }}}, // color_item
|
|
|
|
|
+ {{{ 0.706, 0.706, 0.706,1 }}}, // color_inner
|
|
|
|
|
+ {{{ 0.6, 0.6, 0.6,1 }}}, // color_inner_selected
|
|
|
|
|
+ BND_COLOR_TEXT, // color_text
|
|
|
|
|
+ BND_COLOR_TEXT_SELECTED, // color_text_selected
|
|
|
|
|
+ -20, // shade_top
|
|
|
|
|
+ 0, // shade_down
|
|
|
|
|
+ },
|
|
|
|
|
+ // sliderTheme
|
|
|
|
|
+ {
|
|
|
|
|
+ {{{ 0.098,0.098,0.098,1 }}}, // color_outline
|
|
|
|
|
+ {{{ 0.502,0.502,0.502,1 }}}, // color_item
|
|
|
|
|
+ {{{ 0.706, 0.706, 0.706,1 }}}, // color_inner
|
|
|
|
|
+ {{{ 0.6, 0.6, 0.6,1 }}}, // color_inner_selected
|
|
|
|
|
+ BND_COLOR_TEXT, // color_text
|
|
|
|
|
+ BND_COLOR_TEXT_SELECTED, // color_text_selected
|
|
|
|
|
+ -20, // shade_top
|
|
|
|
|
+ 0, // shade_down
|
|
|
|
|
+ },
|
|
|
|
|
+ // scrollBarTheme
|
|
|
|
|
+ {
|
|
|
|
|
+ {{{ 0.196,0.196,0.196,1 }}}, // color_outline
|
|
|
|
|
+ {{{ 0.502,0.502,0.502,1 }}}, // color_item
|
|
|
|
|
+ {{{ 0.314, 0.314, 0.314,0.706 }}}, // color_inner
|
|
|
|
|
+ {{{ 0.392, 0.392, 0.392,0.706 }}}, // color_inner_selected
|
|
|
|
|
+ BND_COLOR_TEXT, // color_text
|
|
|
|
|
+ BND_COLOR_TEXT_SELECTED, // color_text_selected
|
|
|
|
|
+ 5, // shade_top
|
|
|
|
|
+ -5, // shade_down
|
|
|
|
|
+ },
|
|
|
|
|
+ // tooltipTheme
|
|
|
|
|
+ {
|
|
|
|
|
+ {{{ 0,0,0,1 }}}, // color_outline
|
|
|
|
|
+ {{{ 0.392,0.392,0.392,1 }}}, // color_item
|
|
|
|
|
+ {{{ 0.098, 0.098, 0.098, 0.902 }}}, // color_inner
|
|
|
|
|
+ {{{ 0.176, 0.176, 0.176, 0.902 }}}, // color_inner_selected
|
|
|
|
|
+ {{{ 0.627, 0.627, 0.627, 1 }}}, // color_text
|
|
|
|
|
+ BND_COLOR_TEXT_SELECTED, // color_text_selected
|
|
|
|
|
+ 0, // shade_top
|
|
|
|
|
+ 0, // shade_down
|
|
|
|
|
+ },
|
|
|
|
|
+ // menuTheme
|
|
|
|
|
+ {
|
|
|
|
|
+ {{{ 0,0,0,1 }}}, // color_outline
|
|
|
|
|
+ {{{ 0.392,0.392,0.392,1 }}}, // color_item
|
|
|
|
|
+ {{{ 0.098, 0.098, 0.098, 0.902 }}}, // color_inner
|
|
|
|
|
+ {{{ 0.176, 0.176, 0.176, 0.902 }}}, // color_inner_selected
|
|
|
|
|
+ {{{ 0.627, 0.627, 0.627, 1 }}}, // color_text
|
|
|
|
|
+ BND_COLOR_TEXT_SELECTED, // color_text_selected
|
|
|
|
|
+ 0, // shade_top
|
|
|
|
|
+ 0, // shade_down
|
|
|
|
|
+ },
|
|
|
|
|
+ // menuItemTheme
|
|
|
|
|
+ {
|
|
|
|
|
+ {{{ 0,0,0,1 }}}, // color_outline
|
|
|
|
|
+ {{{ 0.675,0.675,0.675,0.502 }}}, // color_item
|
|
|
|
|
+ {{{ 0,0,0,0 }}}, // color_inner
|
|
|
|
|
+ {{{ 0.337,0.502,0.761,1 }}}, // color_inner_selected
|
|
|
|
|
+ BND_COLOR_TEXT_SELECTED, // color_text
|
|
|
|
|
+ BND_COLOR_TEXT, // color_text_selected
|
|
|
|
|
+ 38, // shade_top
|
|
|
|
|
+ 0, // shade_down
|
|
|
|
|
+ },
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
+
|
|
|
|
|
+void bndSetTheme(BNDtheme theme) {
|
|
|
|
|
+ bnd_theme = theme;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const BNDtheme *bndGetTheme() {
|
|
|
|
|
+ return &bnd_theme;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// the handle to the image containing the icon sheet
|
|
|
|
|
+static int bnd_icon_image = -1;
|
|
|
|
|
+
|
|
|
|
|
+void bndSetIconImage(int image) {
|
|
|
|
|
+ bnd_icon_image = image;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// the handle to the UI font
|
|
|
|
|
+static int bnd_font = -1;
|
|
|
|
|
+
|
|
|
|
|
+void bndSetFont(int font) {
|
|
|
|
|
+ bnd_font = font;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
+
|
|
|
|
|
+void bndLabel(NVGcontext *ctx,
|
|
|
|
|
+ float x, float y, float w, float h, int iconid, const char *label) {
|
|
|
|
|
+ bndIconLabelValue(ctx,x,y,w,h,iconid,
|
|
|
|
|
+ bnd_theme.regularTheme.textColor, BND_LEFT,
|
|
|
|
|
+ BND_LABEL_FONT_SIZE, label, NULL);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndToolButton(NVGcontext *ctx,
|
|
|
|
|
+ float x, float y, float w, float h, int flags, BNDwidgetState state,
|
|
|
|
|
+ int iconid, const char *label) {
|
|
|
|
|
+ float cr[4];
|
|
|
|
|
+ NVGcolor shade_top, shade_down;
|
|
|
|
|
+
|
|
|
|
|
+ bndSelectCorners(cr, BND_TOOL_RADIUS, flags);
|
|
|
|
|
+ bndBevelInset(ctx,x,y,w,h,cr[2],cr[3]);
|
|
|
|
|
+ bndInnerColors(&shade_top, &shade_down, &bnd_theme.toolTheme, state, 1);
|
|
|
|
|
+ bndInnerBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], shade_top, shade_down);
|
|
|
|
|
+ bndOutlineBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3],
|
|
|
|
|
+ bndTransparent(bnd_theme.toolTheme.outlineColor));
|
|
|
|
|
+ bndIconLabelValue(ctx,x,y,w,h,iconid,
|
|
|
|
|
+ bndTextColor(&bnd_theme.toolTheme, state), BND_CENTER,
|
|
|
|
|
+ BND_LABEL_FONT_SIZE, label, NULL);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndRadioButton(NVGcontext *ctx,
|
|
|
|
|
+ float x, float y, float w, float h, int flags, BNDwidgetState state,
|
|
|
|
|
+ int iconid, const char *label) {
|
|
|
|
|
+ float cr[4];
|
|
|
|
|
+ NVGcolor shade_top, shade_down;
|
|
|
|
|
+
|
|
|
|
|
+ bndSelectCorners(cr, BND_OPTION_RADIUS, flags);
|
|
|
|
|
+ bndBevelInset(ctx,x,y,w,h,cr[2],cr[3]);
|
|
|
|
|
+ bndInnerColors(&shade_top, &shade_down, &bnd_theme.radioTheme, state, 1);
|
|
|
|
|
+ bndInnerBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], shade_top, shade_down);
|
|
|
|
|
+ bndOutlineBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3],
|
|
|
|
|
+ bndTransparent(bnd_theme.radioTheme.outlineColor));
|
|
|
|
|
+ bndIconLabelValue(ctx,x,y,w,h,iconid,
|
|
|
|
|
+ bndTextColor(&bnd_theme.radioTheme, state), BND_CENTER,
|
|
|
|
|
+ BND_LABEL_FONT_SIZE, label, NULL);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndTextField(NVGcontext *ctx,
|
|
|
|
|
+ float x, float y, float w, float h, int flags, BNDwidgetState state,
|
|
|
|
|
+ int iconid, const char *text, int cbegin, int cend) {
|
|
|
|
|
+ float cr[4];
|
|
|
|
|
+ NVGcolor shade_top, shade_down;
|
|
|
|
|
+
|
|
|
|
|
+ bndSelectCorners(cr, BND_TEXT_RADIUS, flags);
|
|
|
|
|
+ bndBevelInset(ctx,x,y,w,h,cr[2],cr[3]);
|
|
|
|
|
+ bndInnerColors(&shade_top, &shade_down, &bnd_theme.textFieldTheme, state, 0);
|
|
|
|
|
+ bndInnerBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], shade_top, shade_down);
|
|
|
|
|
+ bndOutlineBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3],
|
|
|
|
|
+ bndTransparent(bnd_theme.textFieldTheme.outlineColor));
|
|
|
|
|
+ if (state != BND_ACTIVE) {
|
|
|
|
|
+ cend = -1;
|
|
|
|
|
+ }
|
|
|
|
|
+ bndIconLabelCaret(ctx,x,y,w,h,iconid,
|
|
|
|
|
+ bndTextColor(&bnd_theme.textFieldTheme, state), BND_LABEL_FONT_SIZE,
|
|
|
|
|
+ text, bnd_theme.textFieldTheme.itemColor, cbegin, cend);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndOptionButton(NVGcontext *ctx,
|
|
|
|
|
+ float x, float y, float w, float h, BNDwidgetState state,
|
|
|
|
|
+ const char *label) {
|
|
|
|
|
+ float ox, oy;
|
|
|
|
|
+ NVGcolor shade_top, shade_down;
|
|
|
|
|
+
|
|
|
|
|
+ ox = x;
|
|
|
|
|
+ oy = y+h-BND_OPTION_HEIGHT-3;
|
|
|
|
|
+
|
|
|
|
|
+ bndBevelInset(ctx,ox,oy,
|
|
|
|
|
+ BND_OPTION_WIDTH,BND_OPTION_HEIGHT,
|
|
|
|
|
+ BND_OPTION_RADIUS,BND_OPTION_RADIUS);
|
|
|
|
|
+ bndInnerColors(&shade_top, &shade_down, &bnd_theme.optionTheme, state, 1);
|
|
|
|
|
+ bndInnerBox(ctx,ox,oy,
|
|
|
|
|
+ BND_OPTION_WIDTH,BND_OPTION_HEIGHT,
|
|
|
|
|
+ BND_OPTION_RADIUS,BND_OPTION_RADIUS,BND_OPTION_RADIUS,BND_OPTION_RADIUS,
|
|
|
|
|
+ shade_top, shade_down);
|
|
|
|
|
+ bndOutlineBox(ctx,ox,oy,
|
|
|
|
|
+ BND_OPTION_WIDTH,BND_OPTION_HEIGHT,
|
|
|
|
|
+ BND_OPTION_RADIUS,BND_OPTION_RADIUS,BND_OPTION_RADIUS,BND_OPTION_RADIUS,
|
|
|
|
|
+ bndTransparent(bnd_theme.optionTheme.outlineColor));
|
|
|
|
|
+ if (state == BND_ACTIVE) {
|
|
|
|
|
+ bndCheck(ctx,ox,oy, bndTransparent(bnd_theme.optionTheme.itemColor));
|
|
|
|
|
+ }
|
|
|
|
|
+ bndIconLabelValue(ctx,x+12,y,w-12,h,-1,
|
|
|
|
|
+ bndTextColor(&bnd_theme.optionTheme, state), BND_LEFT,
|
|
|
|
|
+ BND_LABEL_FONT_SIZE, label, NULL);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndChoiceButton(NVGcontext *ctx,
|
|
|
|
|
+ float x, float y, float w, float h, int flags, BNDwidgetState state,
|
|
|
|
|
+ int iconid, const char *label) {
|
|
|
|
|
+ float cr[4];
|
|
|
|
|
+ NVGcolor shade_top, shade_down;
|
|
|
|
|
+
|
|
|
|
|
+ bndSelectCorners(cr, BND_OPTION_RADIUS, flags);
|
|
|
|
|
+ bndBevelInset(ctx,x,y,w,h,cr[2],cr[3]);
|
|
|
|
|
+ bndInnerColors(&shade_top, &shade_down, &bnd_theme.choiceTheme, state, 1);
|
|
|
|
|
+ bndInnerBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], shade_top, shade_down);
|
|
|
|
|
+ bndOutlineBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3],
|
|
|
|
|
+ bndTransparent(bnd_theme.choiceTheme.outlineColor));
|
|
|
|
|
+ bndIconLabelValue(ctx,x,y,w,h,iconid,
|
|
|
|
|
+ bndTextColor(&bnd_theme.choiceTheme, state), BND_LEFT,
|
|
|
|
|
+ BND_LABEL_FONT_SIZE, label, NULL);
|
|
|
|
|
+ bndUpDownArrow(ctx,x+w-10,y+10,5,
|
|
|
|
|
+ bndTransparent(bnd_theme.choiceTheme.itemColor));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndNumberField(NVGcontext *ctx,
|
|
|
|
|
+ float x, float y, float w, float h, int flags, BNDwidgetState state,
|
|
|
|
|
+ const char *label, const char *value) {
|
|
|
|
|
+ float cr[4];
|
|
|
|
|
+ NVGcolor shade_top, shade_down;
|
|
|
|
|
+
|
|
|
|
|
+ bndSelectCorners(cr, BND_NUMBER_RADIUS, flags);
|
|
|
|
|
+ bndBevelInset(ctx,x,y,w,h,cr[2],cr[3]);
|
|
|
|
|
+ bndInnerColors(&shade_top, &shade_down, &bnd_theme.numberFieldTheme, state, 0);
|
|
|
|
|
+ bndInnerBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], shade_top, shade_down);
|
|
|
|
|
+ bndOutlineBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3],
|
|
|
|
|
+ bndTransparent(bnd_theme.numberFieldTheme.outlineColor));
|
|
|
|
|
+ bndIconLabelValue(ctx,x,y,w,h,-1,
|
|
|
|
|
+ bndTextColor(&bnd_theme.numberFieldTheme, state), BND_CENTER,
|
|
|
|
|
+ BND_LABEL_FONT_SIZE, label, value);
|
|
|
|
|
+ bndArrow(ctx,x+8,y+10,-BND_NUMBER_ARROW_SIZE,
|
|
|
|
|
+ bndTransparent(bnd_theme.numberFieldTheme.itemColor));
|
|
|
|
|
+ bndArrow(ctx,x+w-8,y+10,BND_NUMBER_ARROW_SIZE,
|
|
|
|
|
+ bndTransparent(bnd_theme.numberFieldTheme.itemColor));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndSlider(NVGcontext *ctx,
|
|
|
|
|
+ float x, float y, float w, float h, int flags, BNDwidgetState state,
|
|
|
|
|
+ float progress, const char *label, const char *value) {
|
|
|
|
|
+ float cr[4];
|
|
|
|
|
+ NVGcolor shade_top, shade_down;
|
|
|
|
|
+
|
|
|
|
|
+ bndSelectCorners(cr, BND_NUMBER_RADIUS, flags);
|
|
|
|
|
+ bndBevelInset(ctx,x,y,w,h,cr[2],cr[3]);
|
|
|
|
|
+ bndInnerColors(&shade_top, &shade_down, &bnd_theme.sliderTheme, state, 0);
|
|
|
|
|
+ bndInnerBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], shade_top, shade_down);
|
|
|
|
|
+
|
|
|
|
|
+ if (state == BND_ACTIVE) {
|
|
|
|
|
+ shade_top = bndOffsetColor(
|
|
|
|
|
+ bnd_theme.sliderTheme.itemColor, bnd_theme.sliderTheme.shadeTop);
|
|
|
|
|
+ shade_down = bndOffsetColor(
|
|
|
|
|
+ bnd_theme.sliderTheme.itemColor, bnd_theme.sliderTheme.shadeDown);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ shade_top = bndOffsetColor(
|
|
|
|
|
+ bnd_theme.sliderTheme.itemColor, bnd_theme.sliderTheme.shadeDown);
|
|
|
|
|
+ shade_down = bndOffsetColor(
|
|
|
|
|
+ bnd_theme.sliderTheme.itemColor, bnd_theme.sliderTheme.shadeTop);
|
|
|
|
|
+ }
|
|
|
|
|
+ nvgScissor(ctx,x,y,8+(w-8)*bnd_clamp(progress,0,1),h);
|
|
|
|
|
+ bndInnerBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], shade_top, shade_down);
|
|
|
|
|
+ nvgResetScissor(ctx);
|
|
|
|
|
+
|
|
|
|
|
+ bndOutlineBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3],
|
|
|
|
|
+ bndTransparent(bnd_theme.sliderTheme.outlineColor));
|
|
|
|
|
+ bndIconLabelValue(ctx,x,y,w,h,-1,
|
|
|
|
|
+ bndTextColor(&bnd_theme.sliderTheme, state), BND_CENTER,
|
|
|
|
|
+ BND_LABEL_FONT_SIZE, label, value);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndScrollBar(NVGcontext *ctx,
|
|
|
|
|
+ float x, float y, float w, float h, BNDwidgetState state,
|
|
|
|
|
+ float offset, float size) {
|
|
|
|
|
+
|
|
|
|
|
+ bndBevelInset(ctx,x,y,w,h,
|
|
|
|
|
+ BND_SCROLLBAR_RADIUS, BND_SCROLLBAR_RADIUS);
|
|
|
|
|
+ bndInnerBox(ctx,x,y,w,h,
|
|
|
|
|
+ BND_SCROLLBAR_RADIUS,BND_SCROLLBAR_RADIUS,
|
|
|
|
|
+ BND_SCROLLBAR_RADIUS,BND_SCROLLBAR_RADIUS,
|
|
|
|
|
+ bndOffsetColor(
|
|
|
|
|
+ bnd_theme.scrollBarTheme.innerColor, 3*bnd_theme.scrollBarTheme.shadeDown),
|
|
|
|
|
+ bndOffsetColor(
|
|
|
|
|
+ bnd_theme.scrollBarTheme.innerColor, 3*bnd_theme.scrollBarTheme.shadeTop));
|
|
|
|
|
+ bndOutlineBox(ctx,x,y,w,h,
|
|
|
|
|
+ BND_SCROLLBAR_RADIUS,BND_SCROLLBAR_RADIUS,
|
|
|
|
|
+ BND_SCROLLBAR_RADIUS,BND_SCROLLBAR_RADIUS,
|
|
|
|
|
+ bndTransparent(bnd_theme.scrollBarTheme.outlineColor));
|
|
|
|
|
+
|
|
|
|
|
+ NVGcolor itemColor = bndOffsetColor(
|
|
|
|
|
+ bnd_theme.scrollBarTheme.itemColor,
|
|
|
|
|
+ (state == BND_ACTIVE)?BND_SCROLLBAR_ACTIVE_SHADE:0);
|
|
|
|
|
+
|
|
|
|
|
+ bndScrollHandleRect(&x,&y,&w,&h,offset,size);
|
|
|
|
|
+
|
|
|
|
|
+ bndInnerBox(ctx,x,y,w,h,
|
|
|
|
|
+ BND_SCROLLBAR_RADIUS,BND_SCROLLBAR_RADIUS,
|
|
|
|
|
+ BND_SCROLLBAR_RADIUS,BND_SCROLLBAR_RADIUS,
|
|
|
|
|
+ bndOffsetColor(
|
|
|
|
|
+ itemColor, 3*bnd_theme.scrollBarTheme.shadeTop),
|
|
|
|
|
+ bndOffsetColor(
|
|
|
|
|
+ itemColor, 3*bnd_theme.scrollBarTheme.shadeDown));
|
|
|
|
|
+ bndOutlineBox(ctx,x,y,w,h,
|
|
|
|
|
+ BND_SCROLLBAR_RADIUS,BND_SCROLLBAR_RADIUS,
|
|
|
|
|
+ BND_SCROLLBAR_RADIUS,BND_SCROLLBAR_RADIUS,
|
|
|
|
|
+ bndTransparent(bnd_theme.scrollBarTheme.outlineColor));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndMenuBackground(NVGcontext *ctx,
|
|
|
|
|
+ float x, float y, float w, float h, int flags) {
|
|
|
|
|
+ float cr[4];
|
|
|
|
|
+ NVGcolor shade_top, shade_down;
|
|
|
|
|
+
|
|
|
|
|
+ bndSelectCorners(cr, BND_MENU_RADIUS, flags);
|
|
|
|
|
+ bndInnerColors(&shade_top, &shade_down, &bnd_theme.menuTheme,
|
|
|
|
|
+ BND_DEFAULT, 0);
|
|
|
|
|
+ bndInnerBox(ctx,x,y,w,h+1,cr[0],cr[1],cr[2],cr[3], shade_top, shade_down);
|
|
|
|
|
+ bndOutlineBox(ctx,x,y,w,h+1,cr[0],cr[1],cr[2],cr[3],
|
|
|
|
|
+ bndTransparent(bnd_theme.menuTheme.outlineColor));
|
|
|
|
|
+ bndDropShadow(ctx,x,y,w,h,BND_MENU_RADIUS,
|
|
|
|
|
+ BND_SHADOW_FEATHER,BND_SHADOW_ALPHA);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndTooltipBackground(NVGcontext *ctx, float x, float y, float w, float h) {
|
|
|
|
|
+ NVGcolor shade_top, shade_down;
|
|
|
|
|
+
|
|
|
|
|
+ bndInnerColors(&shade_top, &shade_down, &bnd_theme.tooltipTheme,
|
|
|
|
|
+ BND_DEFAULT, 0);
|
|
|
|
|
+ bndInnerBox(ctx,x,y,w,h+1,
|
|
|
|
|
+ BND_MENU_RADIUS,BND_MENU_RADIUS,BND_MENU_RADIUS,BND_MENU_RADIUS,
|
|
|
|
|
+ shade_top, shade_down);
|
|
|
|
|
+ bndOutlineBox(ctx,x,y,w,h+1,
|
|
|
|
|
+ BND_MENU_RADIUS,BND_MENU_RADIUS,BND_MENU_RADIUS,BND_MENU_RADIUS,
|
|
|
|
|
+ bndTransparent(bnd_theme.tooltipTheme.outlineColor));
|
|
|
|
|
+ bndDropShadow(ctx,x,y,w,h,BND_MENU_RADIUS,
|
|
|
|
|
+ BND_SHADOW_FEATHER,BND_SHADOW_ALPHA);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndMenuLabel(NVGcontext *ctx,
|
|
|
|
|
+ float x, float y, float w, float h, int iconid, const char *label) {
|
|
|
|
|
+ bndIconLabelValue(ctx,x,y,w,h,iconid,
|
|
|
|
|
+ bnd_theme.menuTheme.textColor, BND_LEFT,
|
|
|
|
|
+ BND_LABEL_FONT_SIZE, label, NULL);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndMenuItem(NVGcontext *ctx,
|
|
|
|
|
+ float x, float y, float w, float h, BNDwidgetState state,
|
|
|
|
|
+ int iconid, const char *label) {
|
|
|
|
|
+ if (state != BND_DEFAULT) {
|
|
|
|
|
+ bndInnerBox(ctx,x,y,w,h,0,0,0,0,
|
|
|
|
|
+ bndOffsetColor(bnd_theme.menuItemTheme.innerSelectedColor,
|
|
|
|
|
+ bnd_theme.menuItemTheme.shadeTop),
|
|
|
|
|
+ bndOffsetColor(bnd_theme.menuItemTheme.innerSelectedColor,
|
|
|
|
|
+ bnd_theme.menuItemTheme.shadeDown));
|
|
|
|
|
+ state = BND_ACTIVE;
|
|
|
|
|
+ }
|
|
|
|
|
+ bndIconLabelValue(ctx,x,y,w,h,iconid,
|
|
|
|
|
+ bndTextColor(&bnd_theme.menuItemTheme, state), BND_LEFT,
|
|
|
|
|
+ BND_LABEL_FONT_SIZE, label, NULL);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
+
|
|
|
|
|
+void bndRoundedBox(NVGcontext *ctx, float x, float y, float w, float h,
|
|
|
|
|
+ float cr0, float cr1, float cr2, float cr3) {
|
|
|
|
|
+ float d;
|
|
|
|
|
+
|
|
|
|
|
+ w = fmaxf(0, w);
|
|
|
|
|
+ h = fmaxf(0, h);
|
|
|
|
|
+ d = fminf(w, h);
|
|
|
|
|
+
|
|
|
|
|
+ nvgMoveTo(ctx, x,y+h*0.5f);
|
|
|
|
|
+ nvgArcTo(ctx, x,y, x+w,y, fminf(cr0, d/2));
|
|
|
|
|
+ nvgArcTo(ctx, x+w,y, x+w,y+h, fminf(cr1, d/2));
|
|
|
|
|
+ nvgArcTo(ctx, x+w,y+h, x,y+h, fminf(cr2, d/2));
|
|
|
|
|
+ nvgArcTo(ctx, x,y+h, x,y, fminf(cr3, d/2));
|
|
|
|
|
+ nvgClosePath(ctx);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+NVGcolor bndTransparent(NVGcolor color) {
|
|
|
|
|
+ color.a *= BND_TRANSPARENT_ALPHA;
|
|
|
|
|
+ return color;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+NVGcolor bndOffsetColor(NVGcolor color, int delta) {
|
|
|
|
|
+ float offset = (float)delta / 255.0f;
|
|
|
|
|
+ return delta?(
|
|
|
|
|
+ nvgRGBAf(
|
|
|
|
|
+ bnd_clamp(color.r+offset,0,1),
|
|
|
|
|
+ bnd_clamp(color.g+offset,0,1),
|
|
|
|
|
+ bnd_clamp(color.b+offset,0,1),
|
|
|
|
|
+ color.a)
|
|
|
|
|
+ ):color;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndBevelInset(NVGcontext *ctx, float x, float y, float w, float h,
|
|
|
|
|
+ float cr2, float cr3) {
|
|
|
|
|
+ float d;
|
|
|
|
|
+
|
|
|
|
|
+ y -= 0.5f;
|
|
|
|
|
+ d = fminf(w, h);
|
|
|
|
|
+ cr2 = fminf(cr2, d/2);
|
|
|
|
|
+ cr3 = fminf(cr3, d/2);
|
|
|
|
|
+
|
|
|
|
|
+ nvgBeginPath(ctx);
|
|
|
|
|
+ nvgMoveTo(ctx, x+w,y+h-cr2);
|
|
|
|
|
+ nvgArcTo(ctx, x+w,y+h, x,y+h, cr2);
|
|
|
|
|
+ nvgArcTo(ctx, x,y+h, x,y, cr3);
|
|
|
|
|
+
|
|
|
|
|
+ NVGcolor bevelColor = bndOffsetColor(bnd_theme.backgroundColor,
|
|
|
|
|
+ BND_BEVEL_SHADE);
|
|
|
|
|
+
|
|
|
|
|
+ nvgStrokeWidth(ctx, 1);
|
|
|
|
|
+ nvgStrokePaint(ctx,
|
|
|
|
|
+ nvgLinearGradient(ctx,
|
|
|
|
|
+ x,y+h-fmaxf(cr2,cr3)-1,
|
|
|
|
|
+ x,y+h-1,
|
|
|
|
|
+ nvgRGBAf(bevelColor.r, bevelColor.g, bevelColor.b, 0),
|
|
|
|
|
+ bevelColor));
|
|
|
|
|
+ nvgStroke(ctx);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndBackground(NVGcontext *ctx, float x, float y, float w, float h) {
|
|
|
|
|
+ nvgBeginPath(ctx);
|
|
|
|
|
+ nvgRect(ctx, x, y, w, h);
|
|
|
|
|
+ nvgFillColor(ctx, bnd_theme.backgroundColor);
|
|
|
|
|
+ nvgFill(ctx);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndIcon(NVGcontext *ctx, float x, float y, int iconid) {
|
|
|
|
|
+ int ix, iy, u, v;
|
|
|
|
|
+ if (bnd_icon_image < 0) return; // no icons loaded
|
|
|
|
|
+
|
|
|
|
|
+ ix = iconid & 0xff;
|
|
|
|
|
+ iy = (iconid>>8) & 0xff;
|
|
|
|
|
+ u = BND_ICON_SHEET_OFFSET_X + ix*BND_ICON_SHEET_GRID;
|
|
|
|
|
+ v = BND_ICON_SHEET_OFFSET_Y + iy*BND_ICON_SHEET_GRID;
|
|
|
|
|
+
|
|
|
|
|
+ nvgBeginPath(ctx);
|
|
|
|
|
+ nvgRect(ctx,x,y,BND_ICON_SHEET_RES,BND_ICON_SHEET_RES);
|
|
|
|
|
+ nvgFillPaint(ctx,
|
|
|
|
|
+ nvgImagePattern(ctx,x-u,y-v,
|
|
|
|
|
+ BND_ICON_SHEET_WIDTH,
|
|
|
|
|
+ BND_ICON_SHEET_HEIGHT,
|
|
|
|
|
+ 0,bnd_icon_image,0));
|
|
|
|
|
+ nvgFill(ctx);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndDropShadow(NVGcontext *ctx, float x, float y, float w, float h,
|
|
|
|
|
+ float r, float feather, float alpha) {
|
|
|
|
|
+
|
|
|
|
|
+ nvgBeginPath(ctx);
|
|
|
|
|
+ y += feather;
|
|
|
|
|
+ h -= feather;
|
|
|
|
|
+
|
|
|
|
|
+ nvgMoveTo(ctx, x-feather, y-feather);
|
|
|
|
|
+ nvgLineTo(ctx, x, y-feather);
|
|
|
|
|
+ nvgLineTo(ctx, x, y+h-feather);
|
|
|
|
|
+ nvgArcTo(ctx, x,y+h,x+r,y+h,r);
|
|
|
|
|
+ nvgArcTo(ctx, x+w,y+h,x+w,y+h-r,r);
|
|
|
|
|
+ nvgLineTo(ctx, x+w, y-feather);
|
|
|
|
|
+ nvgLineTo(ctx, x+w+feather, y-feather);
|
|
|
|
|
+ nvgLineTo(ctx, x+w+feather, y+h+feather);
|
|
|
|
|
+ nvgLineTo(ctx, x-feather, y+h+feather);
|
|
|
|
|
+ nvgClosePath(ctx);
|
|
|
|
|
+
|
|
|
|
|
+ nvgFillPaint(ctx, nvgBoxGradient(ctx,
|
|
|
|
|
+ x - feather*0.5f,y - feather*0.5f,
|
|
|
|
|
+ w + feather,h+feather,
|
|
|
|
|
+ r+feather*0.5f,
|
|
|
|
|
+ feather,
|
|
|
|
|
+ nvgRGBAf(0,0,0,alpha*alpha),
|
|
|
|
|
+ nvgRGBAf(0,0,0,0)));
|
|
|
|
|
+ nvgFill(ctx);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndInnerBox(NVGcontext *ctx, float x, float y, float w, float h,
|
|
|
|
|
+ float cr0, float cr1, float cr2, float cr3,
|
|
|
|
|
+ NVGcolor shade_top, NVGcolor shade_down) {
|
|
|
|
|
+ nvgBeginPath(ctx);
|
|
|
|
|
+ bndRoundedBox(ctx,x+1,y+1,w-2,h-3,
|
|
|
|
|
+ fmaxf(0,cr0-1),fmaxf(0,cr1-1),fmaxf(0,cr2-1),fmaxf(0,cr3-1));
|
|
|
|
|
+ nvgFillPaint(ctx,((h-2)>w)?
|
|
|
|
|
+ nvgLinearGradient(ctx,x,y,x+w,y,shade_top,shade_down):
|
|
|
|
|
+ nvgLinearGradient(ctx,x,y,x,y+h,shade_top,shade_down));
|
|
|
|
|
+ nvgFill(ctx);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndOutlineBox(NVGcontext *ctx, float x, float y, float w, float h,
|
|
|
|
|
+ float cr0, float cr1, float cr2, float cr3, NVGcolor color) {
|
|
|
|
|
+ nvgBeginPath(ctx);
|
|
|
|
|
+ bndRoundedBox(ctx,x+0.5f,y+0.5f,w-1,h-2,cr0,cr1,cr2,cr3);
|
|
|
|
|
+ nvgStrokeColor(ctx,color);
|
|
|
|
|
+ nvgStrokeWidth(ctx,1);
|
|
|
|
|
+ nvgStroke(ctx);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndSelectCorners(float *radiuses, float r, int flags) {
|
|
|
|
|
+ radiuses[0] = (flags & BND_CORNER_TOP_LEFT)?0:r;
|
|
|
|
|
+ radiuses[1] = (flags & BND_CORNER_TOP_RIGHT)?0:r;
|
|
|
|
|
+ radiuses[2] = (flags & BND_CORNER_DOWN_RIGHT)?0:r;
|
|
|
|
|
+ radiuses[3] = (flags & BND_CORNER_DOWN_LEFT)?0:r;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndInnerColors(
|
|
|
|
|
+ NVGcolor *shade_top, NVGcolor *shade_down,
|
|
|
|
|
+ const BNDwidgetTheme *theme, BNDwidgetState state, int flipActive) {
|
|
|
|
|
+
|
|
|
|
|
+ switch(state) {
|
|
|
|
|
+ default:
|
|
|
|
|
+ case BND_DEFAULT: {
|
|
|
|
|
+ *shade_top = bndOffsetColor(theme->innerColor, theme->shadeTop);
|
|
|
|
|
+ *shade_down = bndOffsetColor(theme->innerColor, theme->shadeDown);
|
|
|
|
|
+ } break;
|
|
|
|
|
+ case BND_HOVER: {
|
|
|
|
|
+ NVGcolor color = bndOffsetColor(theme->innerColor, BND_HOVER_SHADE);
|
|
|
|
|
+ *shade_top = bndOffsetColor(color, theme->shadeTop);
|
|
|
|
|
+ *shade_down = bndOffsetColor(color, theme->shadeDown);
|
|
|
|
|
+ } break;
|
|
|
|
|
+ case BND_ACTIVE: {
|
|
|
|
|
+ *shade_top = bndOffsetColor(theme->innerSelectedColor,
|
|
|
|
|
+ flipActive?theme->shadeDown:theme->shadeTop);
|
|
|
|
|
+ *shade_down = bndOffsetColor(theme->innerSelectedColor,
|
|
|
|
|
+ flipActive?theme->shadeTop:theme->shadeDown);
|
|
|
|
|
+ } break;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+NVGcolor bndTextColor(const BNDwidgetTheme *theme, BNDwidgetState state) {
|
|
|
|
|
+ return (state == BND_ACTIVE)?theme->textSelectedColor:theme->textColor;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndIconLabelValue(NVGcontext *ctx, float x, float y, float w, float h,
|
|
|
|
|
+ int iconid, NVGcolor color, int align, float fontsize, const char *label,
|
|
|
|
|
+ const char *value) {
|
|
|
|
|
+ float pleft = BND_PAD_LEFT;
|
|
|
|
|
+ if (label) {
|
|
|
|
|
+ if (iconid >= 0) {
|
|
|
|
|
+ bndIcon(ctx,x+4,y+2,iconid);
|
|
|
|
|
+ pleft += BND_ICON_SHEET_RES;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (bnd_font < 0) return;
|
|
|
|
|
+ nvgFontFaceId(ctx, bnd_font);
|
|
|
|
|
+ nvgFontSize(ctx, fontsize);
|
|
|
|
|
+ nvgBeginPath(ctx);
|
|
|
|
|
+ nvgFillColor(ctx, color);
|
|
|
|
|
+ if (value) {
|
|
|
|
|
+ float label_width = nvgTextBounds(ctx, 1, 1, label, NULL, NULL);
|
|
|
|
|
+ float sep_width = nvgTextBounds(ctx, 1, 1,
|
|
|
|
|
+ BND_LABEL_SEPARATOR, NULL, NULL);
|
|
|
|
|
+
|
|
|
|
|
+ nvgTextAlign(ctx, NVG_ALIGN_LEFT|NVG_ALIGN_BASELINE);
|
|
|
|
|
+ x += pleft;
|
|
|
|
|
+ if (align == BND_CENTER) {
|
|
|
|
|
+ float width = label_width + sep_width
|
|
|
|
|
+ + nvgTextBounds(ctx, 1, 1, value, NULL, NULL);
|
|
|
|
|
+ x += ((w-BND_PAD_RIGHT-pleft)-width)*0.5f;
|
|
|
|
|
+ }
|
|
|
|
|
+ y += h-6;
|
|
|
|
|
+ nvgText(ctx, x, y, label, NULL);
|
|
|
|
|
+ x += label_width;
|
|
|
|
|
+ nvgText(ctx, x, y, BND_LABEL_SEPARATOR, NULL);
|
|
|
|
|
+ x += sep_width;
|
|
|
|
|
+ nvgText(ctx, x, y, value, NULL);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ nvgTextAlign(ctx,
|
|
|
|
|
+ (align==BND_LEFT)?(NVG_ALIGN_LEFT|NVG_ALIGN_BASELINE):
|
|
|
|
|
+ (NVG_ALIGN_CENTER|NVG_ALIGN_BASELINE));
|
|
|
|
|
+ nvgTextBox(ctx,x+pleft,y+h-6,w-BND_PAD_RIGHT-pleft,label, NULL);
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if (iconid >= 0) {
|
|
|
|
|
+ bndIcon(ctx,x+2,y+2,iconid);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndIconLabelCaret(NVGcontext *ctx, float x, float y, float w, float h,
|
|
|
|
|
+ int iconid, NVGcolor color, float fontsize, const char *label,
|
|
|
|
|
+ NVGcolor caretcolor, int cbegin, int cend) {
|
|
|
|
|
+ float bounds[4];
|
|
|
|
|
+ float pleft = BND_TEXT_RADIUS;
|
|
|
|
|
+ if (!label) return;
|
|
|
|
|
+ if (iconid >= 0) {
|
|
|
|
|
+ bndIcon(ctx,x+4,y+2,iconid);
|
|
|
|
|
+ pleft += BND_ICON_SHEET_RES;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (bnd_font < 0) return;
|
|
|
|
|
+
|
|
|
|
|
+ x+=pleft;
|
|
|
|
|
+ y+=h-6;
|
|
|
|
|
+
|
|
|
|
|
+ nvgFontFaceId(ctx, bnd_font);
|
|
|
|
|
+ nvgFontSize(ctx, fontsize);
|
|
|
|
|
+ nvgTextAlign(ctx, NVG_ALIGN_LEFT|NVG_ALIGN_BASELINE);
|
|
|
|
|
+
|
|
|
|
|
+ if (cend >= cbegin) {
|
|
|
|
|
+ float c0,c1;
|
|
|
|
|
+ const char *cb;const char *ce;
|
|
|
|
|
+ static NVGglyphPosition glyphs[BND_MAX_GLYPHS];
|
|
|
|
|
+ int nglyphs = nvgTextGlyphPositions(
|
|
|
|
|
+ ctx, x, y, label, label+cend+1, glyphs, BND_MAX_GLYPHS);
|
|
|
|
|
+ c0=glyphs[0].x;
|
|
|
|
|
+ c1=glyphs[nglyphs-1].x;
|
|
|
|
|
+ cb = label+cbegin; ce = label+cend;
|
|
|
|
|
+ // TODO: this is slow
|
|
|
|
|
+ for (int i=0; i < nglyphs; ++i) {
|
|
|
|
|
+ if (glyphs[i].str == cb)
|
|
|
|
|
+ c0 = glyphs[i].x;
|
|
|
|
|
+ if (glyphs[i].str == ce)
|
|
|
|
|
+ c1 = glyphs[i].x;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ nvgTextBounds(ctx,x,y,label,NULL, bounds);
|
|
|
|
|
+ nvgBeginPath(ctx);
|
|
|
|
|
+ if (cbegin == cend) {
|
|
|
|
|
+ nvgFillColor(ctx, nvgRGBf(0.337,0.502,0.761));
|
|
|
|
|
+ nvgRect(ctx, c0-1, bounds[1], 2, bounds[3]-bounds[1]);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ nvgFillColor(ctx, caretcolor);
|
|
|
|
|
+ nvgRect(ctx, c0-1, bounds[1], c1-c0+1, bounds[3]-bounds[1]);
|
|
|
|
|
+ }
|
|
|
|
|
+ nvgFill(ctx);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ nvgBeginPath(ctx);
|
|
|
|
|
+ nvgFillColor(ctx, color);
|
|
|
|
|
+ nvgTextBox(ctx,x,y,w-BND_TEXT_RADIUS-pleft,label, NULL);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndCheck(NVGcontext *ctx, float ox, float oy, NVGcolor color) {
|
|
|
|
|
+ nvgBeginPath(ctx);
|
|
|
|
|
+ nvgStrokeWidth(ctx,2);
|
|
|
|
|
+ nvgStrokeColor(ctx,color);
|
|
|
|
|
+ nvgLineCap(ctx,NVG_BUTT);
|
|
|
|
|
+ nvgLineJoin(ctx,NVG_MITER);
|
|
|
|
|
+ nvgMoveTo(ctx,ox+4,oy+5);
|
|
|
|
|
+ nvgLineTo(ctx,ox+7,oy+8);
|
|
|
|
|
+ nvgLineTo(ctx,ox+14,oy+1);
|
|
|
|
|
+ nvgStroke(ctx);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndArrow(NVGcontext *ctx, float x, float y, float s, NVGcolor color) {
|
|
|
|
|
+ nvgBeginPath(ctx);
|
|
|
|
|
+ nvgMoveTo(ctx,x,y);
|
|
|
|
|
+ nvgLineTo(ctx,x-s,y+s);
|
|
|
|
|
+ nvgLineTo(ctx,x-s,y-s);
|
|
|
|
|
+ nvgClosePath(ctx);
|
|
|
|
|
+ nvgFillColor(ctx,color);
|
|
|
|
|
+ nvgFill(ctx);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndUpDownArrow(NVGcontext *ctx, float x, float y, float s, NVGcolor color) {
|
|
|
|
|
+ float w;
|
|
|
|
|
+
|
|
|
|
|
+ nvgBeginPath(ctx);
|
|
|
|
|
+ w = 1.1f*s;
|
|
|
|
|
+ nvgMoveTo(ctx,x,y-1);
|
|
|
|
|
+ nvgLineTo(ctx,x+0.5*w,y-s-1);
|
|
|
|
|
+ nvgLineTo(ctx,x+w,y-1);
|
|
|
|
|
+ nvgClosePath(ctx);
|
|
|
|
|
+ nvgMoveTo(ctx,x,y+1);
|
|
|
|
|
+ nvgLineTo(ctx,x+0.5*w,y+s+1);
|
|
|
|
|
+ nvgLineTo(ctx,x+w,y+1);
|
|
|
|
|
+ nvgClosePath(ctx);
|
|
|
|
|
+ nvgFillColor(ctx,color);
|
|
|
|
|
+ nvgFill(ctx);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void bndScrollHandleRect(float *x, float *y, float *w, float *h,
|
|
|
|
|
+ float offset, float size) {
|
|
|
|
|
+ size = bnd_clamp(size,0,1);
|
|
|
|
|
+ offset = bnd_clamp(offset,0,1);
|
|
|
|
|
+ if ((*h) > (*w)) {
|
|
|
|
|
+ float hs = fmaxf(size*(*h), (*w)+1);
|
|
|
|
|
+ *y = (*y) + ((*h)-hs)*offset;
|
|
|
|
|
+ *h = hs;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ float ws = fmaxf(size*(*w), (*h)-1);
|
|
|
|
|
+ *x = (*x) + ((*w)-ws)*offset;
|
|
|
|
|
+ *w = ws;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
+
|
|
|
|
|
+#ifdef BND_INLINE
|
|
|
|
|
+#undef BND_INLINE
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+#endif // BLENDISH_IMPLEMENTATION
|