LabeledRect DebriefingScreen::initialize(int text_id, bool do_score) { Resource rsrc("text", "txt", text_id); _message.assign(utf8::decode(rsrc.data())); int text_height = GetInterfaceTextHeightFromWidth(_message, kLarge, kTextWidth); Rect text_bounds(0, 0, kTextWidth, text_height); if (do_score) { text_bounds.bottom += kScoreTableHeight; } text_bounds.center_in(viewport()); LabeledRect data_item = interface_item(text_bounds); _pix_bounds = pix_bounds(data_item); _message_bounds = text_bounds; _message_bounds.offset(-_pix_bounds.left, -_pix_bounds.top); return data_item; }
static void dotext(double x, double y, obj *p) /* print text strings of p in proper vertical spacing */ { double h, v, w, dely, *bnd; int i, j, m, n, t; int nt2 = p->o_nt2; bnd = text_bounds(p); v = bnd[3]; /* includes ABOVE/BELOW attributes */ j = text[p->o_nt1].t_line; new_color(p->o_text); for (h = w = 0, i = p->o_nt1; i < nt2; h = w = 0) { /* calculate position of baseline for this line--assumed to be down 3/4 of maximum character height from top of line */ for (m = 0, n = i; n < nt2 && text[n].t_line == j; n++) { w += text[n].t_width*72/pgscale; if (abs(text[n].t_size) > m) m = abs(text[n].t_size); } dely = (double) m / pgscale; /* max size, in inches */ t = text[i].t_type; #if 0 /* Note the adjustments for ABOVE and BELOW are permanent--affect all subsequent strings in this object */ if (t & ABOVE) v += dely / 2; else if (t & BELOW) v -= dely / 2; #endif dely *= .75; if (t & RJUST) h = w; else if (t & CENTER) h = w/2; newlabel(t, text[i].t_val, abs(text[i].t_font), x-h, y + v - dely, text[i].t_size / pgscale, text[i].t_width * 72 / pgscale); v -= (double) abs(text[i].t_space) / pgscale; while (++i < n) addlabel(text[i].t_type, text[i].t_val, text[i].t_font, text[i].t_size / pgscale, text[i].t_width * 72 / pgscale); j = text[i].t_line; /* line numbers not necessarily consecutive! */ } }
static void objtext(double x, double y, obj *p) { double *bnd; int i, nt2 = (unsigned int) p->o_nt2, t; t = text[p->o_nt1].t_type; for (i = p->o_nt1; i < nt2; i++) if (text[i].t_type != t) break; if (i == nt2 && p->o_type != TEXT) { /* all strings same type */ bnd = text_bounds(p); if (t & RJUST) x += (bnd[2] - bnd[0]) / 2; if (t & LJUST) x -= (bnd[2] - bnd[0]) / 2; } dotext(x, y, p); }
void get_tot_bounds(obj *o, float *box, int flag) { double *tbox; double xc, yc; get_bounds(o, box, flag); if (o->o_type == TEXT) /* Then don't do text_bounds, it ignores */ return; /* transformations. */ if (o->o_nt1 < o->o_nt2) { /* some associated strings */ tbox = text_bounds(o); xc = Xformx(o, 0, o->o_x, o->o_y); yc = Xformy(o, 0, o->o_x, o->o_y); if (tbox[0] + xc < box[0]) box[0] = tbox[0] + xc; if (tbox[1] + yc < box[1]) box[1] = tbox[1] + yc; if (tbox[2] + xc > box[2]) box[2] = tbox[2] + xc; if (tbox[3] + yc > box[3]) box[3] = tbox[3] + yc; } }
int text_width(const char *str) { //@TODO deprecate in favour of text_bounds(..) int width, height; text_bounds(str, width, height); return width; }
char *field_(const char *name, int color, int length, int height, const char *initval, int initmode, int fieldtype = FIELDEDIT) { editor *e = useeditor(name, initmode, false, initval); // generate a new editor if necessary if(layoutpass) { if(initval && e->mode==EDITORFOCUSED && (e!=currentfocus() || fieldmode == FIELDSHOW)) { if(strcmp(e->lines[0].text, initval)) e->clear(initval); } e->linewrap = (length<0); e->maxx = (e->linewrap) ? -1 : length; e->maxy = (height<=0)?1:-1; e->pixelwidth = abs(length)*FONTW; if(e->linewrap && e->maxy==1) { int temp; text_bounds(e->lines[0].text, temp, e->pixelheight, e->pixelwidth); //only single line editors can have variable height } else e->pixelheight = FONTH*max(height, 1); } int h = e->pixelheight; int w = e->pixelwidth + FONTW; bool wasvertical = isvertical(); if(wasvertical && e->maxy != 1) pushlist(); char *result = NULL; if(visible() && !layoutpass) { e->rendered = true; bool hit = ishit(w, h); if(hit) { if(mousebuttons&G3D_DOWN) //mouse request focus { if(fieldtype==FIELDKEY) e->clear(); useeditor(name, initmode, true); e->mark(false); fieldmode = fieldtype; } } bool editing = (fieldmode != FIELDSHOW) && (e==currentfocus()); if(hit && editing && (mousebuttons&G3D_PRESSED)!=0 && fieldtype==FIELDEDIT) e->hit(int(floor(hitx-(curx+FONTW/2))), int(floor(hity-cury)), (mousebuttons&G3D_DRAGGED)!=0); //mouse request position if(editing && ((fieldmode==FIELDCOMMIT) || (fieldmode==FIELDABORT) || !hit)) // commit field if user pressed enter or wandered out of focus { if(fieldmode==FIELDCOMMIT || (fieldmode!=FIELDABORT && !hit)) result = e->currentline().text; e->active = (e->mode!=EDITORFOCUSED); fieldmode = FIELDSHOW; } else fieldsactive = true; e->draw(curx+FONTW/2, cury, color, hit && editing); notextureshader->set(); glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); if(editing) glColor3f(1, 0, 0); else glColor3ub(color>>16, (color>>8)&0xFF, color&0xFF); rect_(curx, cury, w, h, -1, true); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); defaultshader->set(); }
obj * arcgen(int type) /* handles circular and (eventually) elliptical arcs */ { static double prevwid = HT10; static double prevht = HT5; static double prevrad = HT2; static int dtox[2][4] = { { 1, -1, -1, 1 }, { 1, 1, -1, -1 } }; static int dtoy[2][4] = { { 1, 1, -1, -1 }, { -1, 1, 1, -1 } }; static int dctrx[2][4] = { { 0, -1, 0, 1 }, { 0, 1, 0, -1 } }; static int dctry[2][4] = { { 1, 0, -1, 0 }, { -1, 0, 1, 0 } }; static int nexthv[2][4] = { { U_DIR, L_DIR, D_DIR, R_DIR }, { D_DIR, R_DIR, U_DIR, L_DIR } }; struct objattr obat; double dx2, dy2, phi, r, d, fromx, fromy, tox, toy; int i, head, to, at, cw; obj *p, *ppos; Attr *ap; obat.a_ht = getfval("arrowht"); obat.a_wid = getfval("arrowwid"); obat.a_rad = getfval("arcrad"); obat.a_layer = (int)getfval("curlayer"); obat.a_flags = EDGED; obat.a_weight = obat.a_lcolor = obat.a_pcolor = obat.a_tcolor = -1; obat.a_dashpat.a = (float *)0; set_text(); fromx = curx; fromy = cury; head = to = at = cw = 0; for (i = 0; i < nattr; i++) { ap = &attr[i]; switch (ap->a_type) { default: miscattrs(ap, &obat); break; case HEAD: head += ap->a_val.i; break; case CW: cw = 1; break; case FROM: /* start point of arc */ ppos = ap->a_val.o; fromx = Xformx(ppos, 1, ppos->o_x, ppos->o_y); fromy = Xformy(ppos, 0, ppos->o_x, ppos->o_y); break; case TO: /* end point of arc */ ppos = ap->a_val.o; tox = Xformx(ppos, 1, ppos->o_x, ppos->o_y); toy = Xformy(ppos, 0, ppos->o_x, ppos->o_y); to++; break; case AT: /* center of arc */ ppos = ap->a_val.o; curx = Xformx(ppos, 1, ppos->o_x, ppos->o_y); cury = Xformy(ppos, 0, ppos->o_x, ppos->o_y); at = 1; break; case UP: hvmode = U_DIR; break; case DOWN: hvmode = D_DIR; break; case RIGHT: hvmode = R_DIR; break; case LEFT: hvmode = L_DIR; break; case SAME: obat.a_ht = prevht; obat.a_wid = prevwid; obat.a_rad = prevrad; break; } } if (!at && !to) { /* the defaults are mostly OK */ curx = fromx + obat.a_rad * dctrx[cw][hvmode]; cury = fromy + obat.a_rad * dctry[cw][hvmode]; tox = fromx + obat.a_rad * dtox[cw][hvmode]; toy = fromy + obat.a_rad * dtoy[cw][hvmode]; hvmode = nexthv[cw][hvmode]; } else if (to) { /* then compute center */ dx2 = (tox - fromx) / 2; dy2 = (toy - fromy) / 2; phi = atan2(dy2, dx2) + (cw ? -M_PI_2 : M_PI_2); /* If from, to, at (and possibly radius) are all supplied, * the arc is overdetermined. Recompute the radius (as * well as at (i.e., curx and cury)) in that case. */ if (at) { double alpha; obat.a_rad = sqrt((curx - fromx) * (curx - fromx) + (cury - fromy) * (cury - fromy)); alpha = atan2(toy - cury, tox - curx) - atan2(fromy - cury, fromx - curx); if (alpha < 0.) alpha += 2 * M_PI; if ((!cw && alpha > M_PI) || (cw && alpha < M_PI)) phi += M_PI; } else if (obat.a_rad <= 0.0) obat.a_rad = sqrt(dx2*dx2+dy2*dy2); for (r=obat.a_rad; (d = r*r - (dx2*dx2+dy2*dy2)) <= 0.0; r *= 2) ; /* this kludge gets around too-small radii */ obat.a_rad = r; d = sqrt(d); curx = fromx + dx2 + d * cos(phi); cury = fromy + dy2 + d * sin(phi); } else if (at && !to) { /* do we have all the cases??? */ tox = fromx + obat.a_rad * dtox[cw][hvmode]; toy = fromy + obat.a_rad * dtoy[cw][hvmode]; hvmode = nexthv[cw][hvmode]; } p = makenode(type, N_VAL + 10, obat.a_layer); prevrad = p->o_val[N_VAL+0].f = p->o_val[N_VAL+1].f = obat.a_rad; prevwid = p->o_val[N_VAL+8].f = obat.a_wid; prevht = p->o_val[N_VAL+9].f = obat.a_ht; if (cw) { /* interchange roles of from-to and heads */ double temp; temp = fromx; curx = fromx = tox; tox = temp; temp = fromy; cury = fromy = toy; toy = temp; if (head == HEAD1) head = HEAD2; else if (head == HEAD2) head = HEAD1; p->o_attr |= CW_ARC; } else { curx = tox; cury = toy; } p->o_val[N_VAL+2].f = fromx; p->o_val[N_VAL+3].f = fromy; p->o_val[N_VAL+4].f = tox; p->o_val[N_VAL+5].f = toy; if (head) p->o_attr |= head | arrowfill(); primattrs(p, &obat); text_bounds(p); arc_extreme(p); return(p); }
int text_width(const char *str) { int width, height; text_bounds(str, width, height); return width; }
obj * getnth(obj *p, int nth) /* find nth point of an object */ { float x, y; double *tbox; int n = nth; switch (p->o_type) { default: if (n != 1) yyerror("object has only 1 point defined"); return p; case ARC: if (n > 2) { yyerror("arcs have only 2 points defined"); return p; } /* else fall through to SECTOR case */ case SECTOR: if ((n %= 3) == 0) return p; else if (n == 1) { x = p->o_val[N_VAL+2].f; y = p->o_val[N_VAL+3].f; } else { x = p->o_val[N_VAL+4].f; y = p->o_val[N_VAL+5].f; } break; case BLOCK: while (n--) { p = p->o_next; if (p->o_type <= TEXT) continue; else if (p->o_type == BLOCKEND) { yyerror("[] has less than %d objects", nth); p = p->o_parent; } } return p; case BOX: n %= 8; x = p->o_x + xdelta[n] * p->o_wid / 2; y = p->o_y + ydelta[n] * p->o_ht / 2; break; case ARROW: case LINE: case SPLINE: if (--n > p->o_val[N_VAL+3].f) { yyerror("line has less than %d points", nth); return p; } x = p->o_val[N_VAL + 4 + 2 * n].f; y = p->o_val[N_VAL + 5 + 2 * n].f; break; case CIRCLE: case ELLIPSE: n %= 8; x = xdelta[n] * p->o_wid / 2; y = ydelta[n] * p->o_ht / 2; if (n % 2 == 0) { x *= M_SQRT1_2; y *= M_SQRT1_2; } x += p->o_x; y += p->o_y; break; case TEXT: n %= 8; x = p->o_x; y = p->o_y; tbox = text_bounds(p); if (n >= 0 && n <= 2) x += tbox[2]; if (n >= 2 && n <= 4) y += tbox[3]; if (n >= 4 && n <= 6) x += tbox[0]; if (n == 6 || n == 7 || n == 0) y += tbox[1]; if (n == 1 || n == 5) x += (tbox[0] + tbox[2]) / 2; if (n == 3 || n == 7) y += (tbox[1] + tbox[3]) /2; break; } /* DBK--Here also there is a question of whether x and y should be transformed */ return makepos(x, y, nth, p); }
void DefaultLookAndFeel::drawRotarySlider(Graphics& g, int x, int y, int width, int height, float slider_t, float start_angle, float end_angle, Slider& slider) { static const float stroke_percent = 0.12f; static Font roboto_regular(Typeface::createSystemTypefaceFor(BinaryData::RobotoRegular_ttf, BinaryData::RobotoRegular_ttfSize)); float full_radius = std::min(width / 2.0f, height / 2.0f); float stroke_width = 2.0f * full_radius * stroke_percent; float outer_radius = full_radius - stroke_width; PathStrokeType outer_stroke = PathStrokeType(stroke_width, PathStrokeType::beveled, PathStrokeType::butt); float knob_radius = 0.65f * full_radius; float current_angle = start_angle + slider_t * (end_angle - start_angle); float end_x = full_radius + 0.8f * knob_radius * sin(current_angle); float end_y = full_radius - 0.8f * knob_radius * cos(current_angle); if (slider.getInterval() == 1) { static const float TEXT_W_PERCENT = 0.35f; Rectangle<float> text_bounds(1.0f + width * (1.0f - TEXT_W_PERCENT) / 2.0f, 0.5f * height, width * TEXT_W_PERCENT, 0.5f * height); g.setColour(Colour(0xff464646)); g.fillRoundedRectangle(text_bounds, 2.0f); g.setColour(Colour(0xff999999)); g.setFont(roboto_regular.withPointHeight(0.2f * height)); g.drawFittedText(String(slider.getValue()), text_bounds.getSmallestIntegerContainer(), Justification::horizontallyCentred | Justification::bottom, 1); } Path active_section; bool bipolar = false; bool active = true; SynthSlider* s_slider = dynamic_cast<SynthSlider*>(&slider); if (s_slider) { bipolar = s_slider->isBipolar(); active = s_slider->isActive(); } Path rail; rail.addCentredArc(full_radius, full_radius, outer_radius, outer_radius, 0.0f, start_angle, end_angle, true); if (active) g.setColour(Colour(0xff4a4a4a)); else g.setColour(Colour(0xff333333)); g.strokePath(rail, outer_stroke); if (bipolar) { active_section.addCentredArc(full_radius, full_radius, outer_radius, outer_radius, 0.0f, 0.0f, current_angle - 2.0f * mopo::PI, true); } else { active_section.addCentredArc(full_radius, full_radius, outer_radius, outer_radius, 0.0f, start_angle, current_angle, true); } if (active) g.setColour(Colour(0xffffab00)); else g.setColour(Colour(0xff555555)); g.strokePath(active_section, outer_stroke); if (active) g.setColour(Colour(0xff000000)); else g.setColour(Colour(0xff444444)); g.fillEllipse(full_radius - knob_radius + stroke_width / 2.0f, full_radius - knob_radius + stroke_width / 2.0f, 2.0f * knob_radius - stroke_width, 2.0f * knob_radius - stroke_width); if (active) g.setColour(Colour(0xff666666)); else g.setColour(Colour(0xff555555)); g.drawEllipse(full_radius - knob_radius + 1.0f, full_radius - knob_radius + 1.0f, 2.0f * knob_radius - 2.0f, 2.0f * knob_radius - 2.0f, 2.0f); g.setColour(Colour(0xff999999)); g.drawLine(full_radius, full_radius, end_x, end_y, 1.0f); }
obj * circgen(int type) { static double rad[2] = { HT2, WID2 }; static double rad2[2] = { HT2, HT2 }; struct objattr obat; double xwith, ywith, r, r2; int i, at, t, with; obj *p, *ppos; Attr *ap; obat.a_layer = (int)getfval("curlayer"); obat.a_flags = EDGED; obat.a_weight = obat.a_lcolor = obat.a_pcolor = obat.a_tcolor = -1; obat.a_dashpat.a = (float *)0; at = with = xwith = ywith = 0; if ((t = (type == CIRCLE) ? 0 : 1)) { r = getfval("ellipsewid") / 2; r2 = getfval("ellipseht") / 2; } else r = r2 = getfval("circlerad"); set_text(); for (i = 0; i < nattr; i++) { ap = &attr[i]; switch (ap->a_type) { default: miscattrs(ap, &obat); break; case RADIUS: r = ap->a_val.f; break; case DIAMETER: case WIDTH: r = ap->a_val.f / 2; break; case HEIGHT: r2 = ap->a_val.f / 2; break; case SAME: r = rad[t]; r2 = rad2[t]; break; case WITH: with = ap->a_val.i; break; case AT: ppos = ap->a_val.o; curx = Xformx(ppos, 1, ppos->o_x, ppos->o_y); cury = Xformy(ppos, 0, ppos->o_x, ppos->o_y); at++; break; } } if (type == CIRCLE) r2 = r; /* probably superfluous */ if (with) { if (pic_compat) /* map NE to 2nd, etc. */ with = with == NE ? 2 : with == NW ? 4 : with == SW ? 6 : with == SE ? 8 : with; switch (with) { case NORTH: ywith = -r2; break; case SOUTH: ywith = r2; break; case EAST: xwith = -r; break; case WEST: xwith = r; break; case NE: xwith = -r; ywith = -r2; break; case SE: xwith = -r; ywith = r2; break; case NW: xwith = r; ywith = -r2; break; case SW: xwith = r; ywith = r2; break; case CENTER: case START: case END: break; default: xwith = -r * xdelta[with % 8]; ywith = -r2 * ydelta[with % 8]; if (with % 2 == 0) { xwith *= M_SQRT1_2; ywith *= M_SQRT1_2; } break; } curx += xwith; cury += ywith; } if (!at) { if (isright(hvmode)) curx += r; else if (isleft(hvmode)) curx -= r; else if (isup(hvmode)) cury += r2; else cury -= r2; } if (r <= 0 || r2 <= 0) yyerror("%s has invalid radius %g", (type==CIRCLE) ? "circle" : "ellipse", r<r2 ? r : r2); p = makenode(type, N_VAL, obat.a_layer); p->o_wid = 2 * (rad[t] = r); p->o_ht = 2 * (rad2[t] = r2); primattrs(p, &obat); text_bounds(p); if (isright(hvmode)) curx += r; else if (isleft(hvmode)) curx -= r; else if (isup(hvmode)) cury += r2; else cury -= r2; r += p->o_weight/2; r2 += p->o_weight/2; track_bounds (p->o_x - r, p->o_y - r2, p->o_x + r, p->o_y + r2); return(p); }