Nuklear
Minimal-state, immediate-mode graphical user interface toolkit written in ANSI C.
 
Loading...
Searching...
No Matches
nuklear_link.c
1#include "nuklear.h"
2#include "nuklear_internal.h"
3
4/* ===============================================================
5 *
6 * LINK
7 *
8 * ===============================================================*/
9NK_INTERN void
10nk_link_text_bounds(struct nk_rect bounds, const char *string, int len,
11 struct nk_vec2 padding, nk_flags align, const struct nk_user_font *font,
12 struct nk_rect *out_label, float *out_glyph_width)
13{
14 struct nk_rect label;
15 float glyph_width;
16 float text_width;
17 nk_flags a = align;
18
19 NK_ASSERT(out_label);
20 NK_ASSERT(out_glyph_width);
21 NK_ASSERT(font);
22 if (!out_label || !out_glyph_width || !font) return;
23
24 bounds.h = NK_MAX(bounds.h, 2 * padding.y);
25 glyph_width = font->width(font->userdata, font->height, string, len);
26 text_width = glyph_width + (2.0f * padding.x);
27
28 if (!(a & (NK_TEXT_ALIGN_LEFT | NK_TEXT_ALIGN_CENTERED | NK_TEXT_ALIGN_RIGHT)))
29 a |= NK_TEXT_ALIGN_LEFT;
30 if (!(a & (NK_TEXT_ALIGN_TOP | NK_TEXT_ALIGN_MIDDLE | NK_TEXT_ALIGN_BOTTOM)))
31 a |= NK_TEXT_ALIGN_TOP;
32
33 if (a & NK_TEXT_ALIGN_LEFT) {
34 label.x = bounds.x + padding.x;
35 label.w = NK_MAX(0, bounds.w - 2 * padding.x);
36 } else if (a & NK_TEXT_ALIGN_CENTERED) {
37 label.w = NK_MAX(1, 2 * padding.x + (float)text_width);
38 label.x = (bounds.x + padding.x + ((bounds.w - 2 * padding.x) - label.w) / 2);
39 label.x = NK_MAX(bounds.x + padding.x, label.x);
40 label.w = NK_MIN(bounds.x + bounds.w, label.x + label.w);
41 if (label.w >= label.x) label.w -= label.x;
42 } else {
43 label.x = NK_MAX(bounds.x + padding.x, (bounds.x + bounds.w) - (2 * padding.x + (float)text_width));
44 label.w = (float)text_width + 2 * padding.x;
45 }
46
47 if (a & NK_TEXT_ALIGN_TOP) {
48 label.y = bounds.y + padding.y;
49 label.h = NK_MIN(font->height, bounds.h - 2 * padding.y);
50 } else if (a & NK_TEXT_ALIGN_MIDDLE) {
51 label.y = bounds.y + bounds.h/2.0f - (float)font->height/2.0f;
52 label.h = NK_MAX(bounds.h/2.0f, bounds.h - (bounds.h/2.0f + font->height/2.0f));
53 } else {
54 label.y = bounds.y + bounds.h - font->height;
55 label.h = font->height;
56 }
57
58 *out_label = label;
59 *out_glyph_width = glyph_width;
60}
61NK_LIB void
62nk_draw_link(struct nk_command_buffer *out, const struct nk_rect *bounds,
63 nk_flags state, const struct nk_style_link *style, const char *str, int len,
64 nk_flags align, const struct nk_user_font *font, struct nk_color background)
65{
66 struct nk_text text;
67 struct nk_rect label;
68 struct nk_color color;
69 float glyph_width;
70 nk_bool draw_underline = nk_false;
71
72 NK_ASSERT(out);
73 NK_ASSERT(bounds);
74 NK_ASSERT(style);
75 NK_ASSERT(font);
76 if (!out || !bounds || !style || !font || !str)
77 return;
78
79 if (state & NK_WIDGET_STATE_HOVER)
80 color = style->text_hover;
81 else if (state & NK_WIDGET_STATE_ACTIVED)
82 color = style->text_active;
83 else color = style->text_normal;
84 color = nk_rgb_factor(color, style->color_factor);
85
86 text.padding = style->padding;
87 text.background = background;
88 text.text = color;
89 nk_widget_text(out, *bounds, str, len, &text, align, font);
90
91 if (style->underline == NK_LINK_UNDERLINE_ALWAYS)
92 draw_underline = nk_true;
93 else if (style->underline == NK_LINK_UNDERLINE_HOVER &&
94 (state & (NK_WIDGET_STATE_HOVER|NK_WIDGET_STATE_ACTIVED)))
95 draw_underline = nk_true;
96
97 if (!draw_underline || style->underline_thickness <= 0)
98 return;
99
100 nk_link_text_bounds(*bounds, str, len, style->padding, align, font, &label, &glyph_width);
101 {
102 float x0 = label.x;
103 float x1 = label.x + NK_MIN(glyph_width, label.w);
104 float y = label.y + font->height - style->underline_thickness;
105 if (x1 > x0)
106 nk_stroke_line(out, x0, y, x1, y, style->underline_thickness, color);
107 }
108}
109NK_LIB nk_bool
110nk_do_link(nk_flags *state, struct nk_command_buffer *out,
111 struct nk_rect bounds, const char *str, int len, nk_flags align,
112 const struct nk_style_link *style, const struct nk_input *in,
113 const struct nk_user_font *font, struct nk_color background)
114{
115 struct nk_rect label;
116 struct nk_rect touch;
117 float glyph_width;
118 nk_bool ret;
119
120 NK_ASSERT(state);
121 NK_ASSERT(style);
122 NK_ASSERT(out);
123 NK_ASSERT(str);
124 NK_ASSERT(font);
125 if (!out || !style || !font || !str || !state)
126 return nk_false;
127
128 nk_link_text_bounds(bounds, str, len, style->padding, align, font, &label, &glyph_width);
129 touch.x = label.x - style->touch_padding.x;
130 touch.y = label.y - style->touch_padding.y;
131 touch.w = NK_MIN(glyph_width, label.w) + 2 * style->touch_padding.x;
132 touch.h = font->height + 2 * style->touch_padding.y;
133 if (touch.x < bounds.x) {
134 touch.w -= (bounds.x - touch.x);
135 touch.x = bounds.x;
136 }
137 if (touch.y < bounds.y) {
138 touch.h -= (bounds.y - touch.y);
139 touch.y = bounds.y;
140 }
141 if (touch.x + touch.w > bounds.x + bounds.w)
142 touch.w = NK_MAX(0, bounds.x + bounds.w - touch.x);
143 if (touch.y + touch.h > bounds.y + bounds.h)
144 touch.h = NK_MAX(0, bounds.y + bounds.h - touch.y);
145
146 ret = nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT);
147 nk_draw_link(out, &bounds, *state, style, str, len, align, font, background);
148 return ret;
149}
150NK_API nk_bool
151nk_link_text_styled(struct nk_context *ctx, const struct nk_style_link *style,
152 const char *title, int len, nk_flags align)
153{
154 struct nk_window *win;
155 struct nk_panel *layout;
156 const struct nk_input *in;
157 struct nk_rect bounds;
158 enum nk_widget_layout_states state;
159
160 NK_ASSERT(ctx);
161 NK_ASSERT(style);
162 NK_ASSERT(ctx->current);
163 NK_ASSERT(ctx->current->layout);
164 if (!style || !ctx || !ctx->current || !ctx->current->layout) return 0;
165
166 win = ctx->current;
167 layout = win->layout;
168 state = nk_widget(&bounds, ctx);
169
170 if (!state) return 0;
171 in = (state == NK_WIDGET_ROM || state == NK_WIDGET_DISABLED || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
172 return nk_do_link(&ctx->last_widget_state, &win->buffer, bounds,
173 title, len, align, style, in, ctx->style.font,
174 ctx->style.window.background);
175}
176NK_API nk_bool
177nk_link_text(struct nk_context *ctx, const char *title, int len, nk_flags align)
178{
179 NK_ASSERT(ctx);
180 if (!ctx) return 0;
181 return nk_link_text_styled(ctx, &ctx->style.link, title, len, align);
182}
183NK_API nk_bool
184nk_link_label_styled(struct nk_context *ctx, const struct nk_style_link *style,
185 const char *title, nk_flags align)
186{
187 return nk_link_text_styled(ctx, style, title, nk_strlen(title), align);
188}
189NK_API nk_bool
190nk_link_label(struct nk_context *ctx, const char *title, nk_flags align)
191{
192 return nk_link_text(ctx, title, nk_strlen(title), align);
193}
194NK_API nk_bool
195nk_link_text_underline(struct nk_context *ctx, const char *title, int len,
196 nk_flags align, enum nk_link_underline underline)
197{
198 struct nk_style_link style;
199 NK_ASSERT(ctx);
200 if (!ctx) return 0;
201 style = ctx->style.link;
202 style.underline = underline;
203 return nk_link_text_styled(ctx, &style, title, len, align);
204}
205NK_API nk_bool
206nk_link_label_underline(struct nk_context *ctx, const char *title,
207 nk_flags align, enum nk_link_underline underline)
208{
209 return nk_link_text_underline(ctx, title, nk_strlen(title), align, underline);
210}
211NK_API nk_bool
212nk_link_text_hover_underline(struct nk_context *ctx, const char *title,
213 int len, nk_flags align)
214{
215 return nk_link_text_underline(ctx, title, len, align, NK_LINK_UNDERLINE_HOVER);
216}
217NK_API nk_bool
218nk_link_label_hover_underline(struct nk_context *ctx, const char *title,
219 nk_flags align)
220{
221 return nk_link_text_hover_underline(ctx, title, nk_strlen(title), align);
222}
223NK_API nk_bool
224nk_link_text_no_underline(struct nk_context *ctx, const char *title,
225 int len, nk_flags align)
226{
227 return nk_link_text_underline(ctx, title, len, align, NK_LINK_UNDERLINE_NONE);
228}
229NK_API nk_bool
230nk_link_label_no_underline(struct nk_context *ctx, const char *title,
231 nk_flags align)
232{
233 return nk_link_text_no_underline(ctx, title, nk_strlen(title), align);
234}
235NK_API nk_bool
236nk_link_text_colored(struct nk_context *ctx, const char *title, int len,
237 nk_flags align, struct nk_color color)
238{
239 struct nk_style_link style;
240 NK_ASSERT(ctx);
241 if (!ctx) return 0;
242 style = ctx->style.link;
243 style.text_normal = color;
244 style.text_hover = color;
245 style.text_active = color;
246 return nk_link_text_styled(ctx, &style, title, len, align);
247}
248NK_API nk_bool
249nk_link_label_colored(struct nk_context *ctx, const char *title,
250 nk_flags align, struct nk_color color)
251{
252 return nk_link_text_colored(ctx, title, nk_strlen(title), align, color);
253}
nk_text_width_f width
!< max height of the font
Definition nuklear.h:4075
float height
!< user provided font handle
Definition nuklear.h:4074