// Update desired size of the button. If the size changes, trigger layout // (which will in turn request repaints of affected areas) // To keep size of the button stable (to avoid re-layouts) we use font // line spacing to be the height of the button, even if text is empty. // Note: it might be that for some cases button with no text should collapse // in size but we don't have a need for that yet void Button::RecalculateSize(bool repaintIfSizeDidntChange) { Size prevSize = desiredSize; desiredSize = GetBorderAndPaddingSize(cachedStyle); Graphics *gfx = AllocGraphicsForMeasureText(); CachedStyle *s = cachedStyle; Font *font = GetCachedFont(s->fontName, s->fontSize, s->fontWeight); textDx = 0; float fontDy = font->GetHeight(gfx); RectF bbox; if (text) { bbox = MeasureText(gfx, font, text); textDx = (size_t)bbox.Width; // TODO: round up? // bbox shouldn't be bigger than fontDy. We apply magic adjustment because // bbox is bigger in n-th decimal point CrashIf(fontDy + .5f < bbox.Height); } desiredSize.Width += textDx; desiredSize.Height += (INT)fontDy; // TODO: round up? FreeGraphicsForMeasureText(gfx); if (!prevSize.Equals(desiredSize)) RequestLayout(this); else if (repaintIfSizeDidntChange) RequestRepaint(this); }
ECode CComposingView::MoveCursor( /* [in] */ Int32 keyCode, /* [out] */ Boolean* result) { VALIDATE_NOT_NULL(result); if (keyCode != IKeyEvent::KEYCODE_DPAD_LEFT && keyCode != IKeyEvent::KEYCODE_DPAD_RIGHT) { *result = FALSE; return NOERROR; } if (ComposingStatus_EDIT_PINYIN == mComposingStatus) { Int32 offset = 0; if (keyCode == IKeyEvent::KEYCODE_DPAD_LEFT) offset = -1; else if (keyCode == IKeyEvent::KEYCODE_DPAD_RIGHT) offset = 1; mDecInfo->MoveCursor(offset); } else if (ComposingStatus_SHOW_STRING_LOWERCASE == mComposingStatus) { if (keyCode == IKeyEvent::KEYCODE_DPAD_LEFT || keyCode == IKeyEvent::KEYCODE_DPAD_RIGHT) { mComposingStatus = ComposingStatus_EDIT_PINYIN; Measure(IViewGroupLayoutParams::WRAP_CONTENT, IViewGroupLayoutParams::WRAP_CONTENT); RequestLayout(); } } Invalidate(); *result = TRUE; return NOERROR; }
// TODO: the position still seems a bit off wrt. padding void ButtonVector::RecalculateSize(bool repaintIfSizeDidntChange) { Size prevSize = desiredSize; CachedStyle *s = cachedStyle; desiredSize = GetBorderAndPaddingSize(s); Rect bbox; Brush *brStroke = BrushFromColorData(s->stroke, bbox); if (0.f == s->strokeWidth) { graphicsPath->GetBounds(&bbox); } else { Pen pen(brStroke, s->strokeWidth); // pen widith is multiplied by MiterLimit(), which is 10 by default // so set it explicitly to 1 for the size we expect pen.SetMiterLimit(1.f); pen.SetAlignment(PenAlignmentInset); graphicsPath->GetBounds(&bbox, NULL, &pen); } desiredSize.Width += bbox.Width; desiredSize.Height += bbox.Height; if (!prevSize.Equals(desiredSize)) RequestLayout(this); else if (repaintIfSizeDidntChange) RequestRepaint(this); }
Boolean CComposingView::MoveCursor( /* [in] */ Int32 keyCode) { if (keyCode != IKeyEvent::KEYCODE_DPAD_LEFT && keyCode != IKeyEvent::KEYCODE_DPAD_RIGHT) { return FALSE; } if (EDIT_PINYIN == mComposingStatus) { Int32 offset = 0; if (keyCode == IKeyEvent::KEYCODE_DPAD_LEFT) { offset = -1; } else if (keyCode == IKeyEvent::KEYCODE_DPAD_RIGHT) offset = 1; mDecInfo->MoveCursor(offset); } else if (SHOW_STRING_LOWERCASE == mComposingStatus) { if (keyCode == IKeyEvent::KEYCODE_DPAD_LEFT || keyCode == IKeyEvent::KEYCODE_DPAD_RIGHT) { mComposingStatus = EDIT_PINYIN; Measure(IViewGroupLayoutParams::WRAP_CONTENT, IViewGroupLayoutParams::WRAP_CONTENT); RequestLayout(); } } Invalidate(); return TRUE; }
ECode CComposingView::SetDecodingInfo( /* [in] */ CPinyinIME::DecodingInfo* decInfo, /* [in] */ CPinyinIME::ImeState imeStatus) { mDecInfo = decInfo; if (CPinyinIME::STATE_INPUT == imeStatus) { mComposingStatus = SHOW_PINYIN; mDecInfo->MoveCursorToEdge(FALSE); } else { if (decInfo->GetFixedLen() != 0 || EDIT_PINYIN == mComposingStatus) { mComposingStatus = EDIT_PINYIN; } else { mComposingStatus = SHOW_STRING_LOWERCASE; } mDecInfo->MoveCursor(0); } Measure(IViewGroupLayoutParams::WRAP_CONTENT, IViewGroupLayoutParams::WRAP_CONTENT); RequestLayout(); return Invalidate(); }
void Control::Hide() { if (!IsVisible()) return; RequestRepaint(this); // request repaint before hiding, to trigger repaint bit::Set(stateBits, IsHiddenBit); RequestLayout(this); }
/** * Attach an action to the button. * This updates the button's text with the name and hotkey of the action. * Clicking on the button will fire the attached action. * This is typically called from Client::Scene::AttachController. * @param controller The controller that owns the action. * @param action The action to attach. */ void ActionButton::AttachAction(Control::InputEventController&, Control::InputEventController::VoidActionPtr action) { this->action = action; SetText(fixedText.empty() ? action->GetName() : fixedText); keycap->SetKeyHash(action->GetPrimaryTrigger()); RequestLayout(); }
/** * Set the optional icon to appear on the button, in addition to the text. * * The icon will be sized to the standard size for the button (namely, the * height of the text), so while it is safe to share the icon between * buttons, be aware that it may be modified. * * @param icon A subclass of FillBox to use as an icon, or @c nullptr to * unset the icon. */ void Button::SetIcon(std::shared_ptr<FillBox> icon) { if (this->icon != icon) { this->icon = std::move(icon); FireModelUpdate(Props::ICON); RequestSizing(); RequestLayout(); } }
void FlexGrid::SetMargin(double width, double height) { if (margin.x != width || margin.y != height) { margin.x = width; margin.y = height; FireModelUpdate(Props::MARGIN); RequestLayout(); } }
void FlexGrid::SetPadding(double width, double height) { if (padding.x != width || padding.y != height) { padding.x = width; padding.y = height; FireModelUpdate(Props::MARGIN); RequestLayout(); } }
void Control::Show() { if (IsVisible()) return; // perf: avoid unnecessary repaints bit::Clear(stateBits, IsHiddenBit); // showing/hiding controls might affect layout, so we need // to re-do layout. // Note: not sure if have to RequestRepaint(this) as well RequestLayout(this); }
void Slider::FireModelUpdate(int prop) { switch (prop) { case UiViewModel::Props::FOCUSED: case SUPER::Props::SIZE: case SUPER::Props::ENABLED: case SUPER::Props::PRESSED: RequestLayout(); } SUPER::FireModelUpdate(prop); }
ECode RatingBar::SetNumStars( /* [in] */ Int32 numStars) { if (numStars < 0) { return NOERROR; } mNumStars = numStars; RequestLayout(); return NOERROR; }
void Minimap::OnHudRescaled(const Vec2 &hudScale) { // Maintain the map aspect ratio. rescale = std::min(hudScale.x, hudScale.y); Vec2 sz{MAP_WIDTH * rescale, MAP_HEIGHT * rescale}; SetSize(sz); mapPic->SetSize(sz); RequestLayout(); }
void CCandidateView::ScrollToTarget() { Int32 sx = 0; GetScrollX(&sx); if (mTargetScrollX > sx) { sx += SCROLL_PIXELS; if (sx >= mTargetScrollX) { sx = mTargetScrollX; RequestLayout(); } } else { sx -= SCROLL_PIXELS; if (sx <= mTargetScrollX) { sx = mTargetScrollX; RequestLayout(); } } Int32 tmp = 0; GetScrollY(&tmp); ScrollTo(sx, tmp); Invalidate(); }
ECode CCandidateView::OnTouchEvent( /* [in] */ IMotionEvent* event, /* [out] */ Boolean* res) { VALIDATE_NOT_NULL(res); Boolean tmp = FALSE; if (mGestureDetector->OnTouchEvent(event, &tmp), tmp) { *res = TRUE; return NOERROR; } Int32 action = 0, x = 0, y = 0; event->GetAction(&action); Float fx, fy; event->GetX(&fx); event->GetY(&fy); x = (Int32)fx; y = (Int32)fy; mTouchX = x; switch (action) { case IMotionEvent::ACTION_DOWN: mScrolled = FALSE; Invalidate(); break; case IMotionEvent::ACTION_MOVE: if (y <= 0) { // Fling up!? if (mSelectedIndex >= 0) { mService->PickSuggestionManually(mSelectedIndex); mSelectedIndex = -1; } } Invalidate(); break; case IMotionEvent::ACTION_UP: if (!mScrolled) { if (mSelectedIndex >= 0) { mService->PickSuggestionManually(mSelectedIndex); } } mSelectedIndex = -1; RemoveHighlight(); RequestLayout(); break; } *res = TRUE; return NOERROR; }
/** * Set the value. * * The value will be clamped to the range of the slider. * * @param value The value. */ void Slider::SetValue(double value) { if (value < min) value = min; else if (value > max) value = max; else { // Clamp to the nearest step. value = round(value * (1.0 / step)) * step; } if (this->value != value) { this->value = value; FireModelUpdate(Props::VALUE); valueChangedSignal(value); RequestLayout(); } }
ECode CCandidateView::SetSuggestions( /* [in] */ ArrayOf<ICharSequence*>* suggestions, /* [in] */ Boolean completions, /* [in] */ Boolean typedWordValid) { Clear(); if (suggestions != NULL) { mSuggestions = suggestions->Clone(); } mTypedWordValid = typedWordValid; ScrollTo(0, 0); mTargetScrollX = 0; // Compute the total width OnDraw(NULL); Invalidate(); RequestLayout(); return NOERROR; }
// Update desired size of the button. If the size changes, trigger layout // (which will in turn request repaints of affected areas) // To keep size of the button stable (to avoid re-layouts) we use font // line spacing to be the height of the button, even if text is empty. // Note: it might be that for some cases button with no text should collapse // in size but we don't have a need for that yet void Button::RecalculateSize(bool repaintIfSizeDidntChange) { Size prevSize = desiredSize; desiredSize = GetBorderAndPaddingSize(cachedStyle); Graphics *gfx = AllocGraphicsForMeasureText(); CachedStyle *s = cachedStyle; Font *font = GetCachedFont(s->fontName, s->fontSize, s->fontWeight); textDx = 0; float fontDy = font->GetHeight(gfx); RectF bbox; if (text) { bbox = MeasureText(gfx, font, text); textDx = CeilI(bbox.Width); // I theorize that bbox shouldn't be bigger than fontDy. However, in practice // it is (e.g. for Lucida Grande and text "Page: 0 / 0", bbox.Dy is 19.00 // and fontDy is 18.11). I still want to know if the difference gets even bigger // than that float maxDiff = 1.f; if (bbox.Height > fontDy + maxDiff) { fontDy = bbox.Height; float diff = fontDy + maxDiff - bbox.Height; char *fontName = str::conv::ToUtf8(s->fontName); char *tmp = str::conv::ToUtf8(text); CrashLogFmt("fontDy=%.2f, bbox.Height=%.2f, diff=%.2f (should be > 0) font: %s, text='%s'\r\n", (float)fontDy, (float)bbox.Height, diff, fontName, tmp); CrashIf(diff < 0); } } desiredSize.Width += textDx; desiredSize.Height += CeilI(fontDy); FreeGraphicsForMeasureText(gfx); if (!prevSize.Equals(desiredSize)) RequestLayout(this); else if (repaintIfSizeDidntChange) RequestRepaint(this); }
ECode CComposingView::SetDecodingInfo( /* [in] */ IDecodingInfo* decInfo, /* [in] */ ImeState imeStatus) { mDecInfo = decInfo; if (ImeState_STATE_INPUT == imeStatus) { mComposingStatus = ComposingStatus_SHOW_PINYIN; mDecInfo->MoveCursorToEdge(FALSE); } else { Int32 value = 0; if ((decInfo->GetFixedLen(&value), value) != 0 || ComposingStatus_EDIT_PINYIN == mComposingStatus) { mComposingStatus = ComposingStatus_EDIT_PINYIN; } else { mComposingStatus = ComposingStatus_SHOW_STRING_LOWERCASE; } mDecInfo->MoveCursor(0); } Measure(IViewGroupLayoutParams::WRAP_CONTENT, IViewGroupLayoutParams::WRAP_CONTENT); RequestLayout(); return Invalidate(); }
void FlexGrid::SetFixedHeight(double h) { fixedSize.y = h; RequestLayout(); }
void FlexGrid::SetFixedWidth(double w) { fixedSize.x = w; RequestLayout(); }
void GameScene::OnFinishedLoading() { finishedLoading = true; RequestLayout(); }