void BaseItemEditor::resized() { Rectangle<int> r = getLocalBounds().withHeight((int)headerHeight).reduced(2); Rectangle<int> hr = Rectangle<int>(r); if (item->canBeDisabled) { enabledUI->setBounds(hr.removeFromLeft(hr.getHeight())); } if (!isRoot && item->userCanRemove) { removeBT->setBounds(hr.removeFromRight(hr.getHeight())); hr.removeFromRight(2); } resizedInternalHeader(hr); nameUI->setBounds(hr); r.translate(0, r.getBottom() + 2); r.setHeight(0); //if no override, ensure bottom is set resizedInternalContent(r); if (item->canHaveScripts) { r.setY(r.getBottom() + 2); r.setHeight(scriptManagerUI->getHeight()); scriptManagerUI->setBounds(r); } if (item->canHaveCustomParameters) { r.setY(r.getBottom() + 2); r.setHeight(customParamsUI->getHeight()); customParamsUI->setBounds(r); } r.setY(r.getBottom() + 2); r.setHeight(0); //if no override, ensure bottom is set resizedInternalFooter(r); setSize(getWidth(),r.getBottom()); }
void FullInterface::paintBackground(Graphics& g) { static const DropShadow shadow(Colour(0xcc000000), 3, Point<int>(0, 1)); static const DropShadow logo_shadow(Colour(0xff000000), 8, Point<int>(0, 0)); static const DropShadow component_shadow(Colour(0xcc000000), 5, Point<int>(0, 1)); static Font roboto_reg(Typeface::createSystemTypefaceFor(BinaryData::RobotoRegular_ttf, BinaryData::RobotoRegular_ttfSize)); static Font roboto_light(Typeface::createSystemTypefaceFor(BinaryData::RobotoLight_ttf, BinaryData::RobotoLight_ttfSize)); static const Image helm_small = ImageCache::getFromMemory(BinaryData::helm_icon_32_2x_png, BinaryData::helm_icon_32_2x_pngSize); g.setColour(Colour(0xff212121)); g.fillRect(getLocalBounds()); shadow.drawForRectangle(g, arp_section_->getBounds()); shadow.drawForRectangle(g, global_tool_tip_->getBounds()); shadow.drawForRectangle(g, oscilloscope_->getBounds()); shadow.drawForRectangle(g, Rectangle<int>(92, 8, 244, TOP_HEIGHT)); shadow.drawForRectangle(g, Rectangle<int>(16, 8, 68, 64)); g.setColour(Colour(0xff303030)); g.fillRoundedRectangle(16.0f, 8.0f, 68.0f, 64.0f, 3.0f); g.saveState(); g.setOrigin(18, 8); logo_shadow.drawForImage(g, helm_small); g.restoreState(); g.setColour(Colour(0xff303030)); g.fillRect(92, 8, 244, TOP_HEIGHT); g.setColour(Colour(0xffbbbbbb)); g.setFont(roboto_reg.withPointHeight(10.0f)); g.drawText(TRANS("BPM"), patch_selector_->getX(), beats_per_minute_->getY(), 44, beats_per_minute_->getHeight(), Justification::centred, false); component_shadow.drawForRectangle(g, patch_selector_->getBounds()); paintKnobShadows(g); }
void PathPointComponent::paint (Graphics& g) { if (isMouseOverOrDragging()) g.fillAll (Colours::red); if (selected) { g.setColour (Colours::red); g.drawRect (getLocalBounds()); } g.setColour (Colours::white); g.fillRect (getWidth() / 2 - 3, getHeight() / 2 - 3, 7, 7); g.setColour (Colours::black); if (pointNumber < path->getPoint (index)->getNumPoints() - 1) g.drawRect (getWidth() / 2 - 2, getHeight() / 2 - 2, 5, 5); else g.fillRect (getWidth() / 2 - 2, getHeight() / 2 - 2, 5, 5); }
AffineTransform BrickWallChart::calcTransform () { const Rectangle<int> bounds = getLocalBounds (); const Rectangle<int> r = bounds.reduced (4, 4); AffineTransform t; // scale x from 0..1 to 0..getWidth(), and flip vertical t = AffineTransform::scale (float(r.getWidth()), -1.f); // scale y from gain to 0..1 bounds in r t = t.scaled (1.f, m_scale_y); // scale y from 0..1 to getHeight() t = t.scaled (1.f, float(r.getHeight())); // translate t = t.translated (float(r.getX()), float(r.getBottom())); return t; }
void ComponentOverlay::paint (Graphics& g) { Colour c = Colours::white; if (interest == "selected") { Path selectedRect; selectedRect.addRectangle (getLocalBounds().reduced (2)); g.setColour (c); const float dashLengths[] = { 10.0f, 10.0f }; PathStrokeType stroke (1.0, PathStrokeType::mitered); stroke.createDashedStroke (selectedRect, selectedRect, dashLengths, 2); g.strokePath (selectedRect, stroke); } g.setColour (c); g.drawRect (0, 0, getWidth(), getHeight(), 1); }
void IdeaNewComponent::paint (Graphics& g) { /* This demo code just fills the component's background and draws some placeholder text to get you started. You should replace everything in this method with your own drawing code.. */ g.fillAll (Colours::white); // clear the background g.setColour (Colours::grey); g.drawRect (getLocalBounds(), 1); // draw an outline around the component g.setColour (Colours::lightblue); g.setFont (14.0f); Font cFont = g.getCurrentFont(); // TODO V Figure out how to set the font globally // Figure out how to calculate the font height at the right time. m_fCurrentFontHeight = cFont.getHeight(); }
void ProjectContentComponent::resized() { auto r = getLocalBounds(); r.removeFromRight (10); r.removeFromLeft (15); r.removeFromBottom (40); r.removeFromTop (5); if (header != nullptr) header->setBounds (r.removeFromTop (40)); r.removeFromTop (10); auto sidebarArea = r.removeFromLeft (sidebarTabs.getWidth() != 0 ? sidebarTabs.getWidth() : r.getWidth() / 4); if (sidebarTabs.isVisible()) sidebarTabs.setBounds (sidebarArea); if (resizerBar != nullptr) resizerBar->setBounds (r.withWidth (4)); if (auto* h = dynamic_cast<HeaderComponent*> (header.get())) { h->sidebarTabsWidthChanged (sidebarTabs.getWidth()); r.removeFromRight (h->getUserButtonWidth()); } if (contentView != nullptr) { if (fileNameLabel != nullptr && fileNameLabel->isVisible()) fileNameLabel->setBounds (r.removeFromTop (15)); contentView->setBounds (r); } if (logo != nullptr) logo->setBounds (r.reduced (r.getWidth() / 6, r.getHeight() / 6)); }
void PowerPageComponent::resized() { auto bounds = getLocalBounds(); powerSpinner->setBounds(0, 0, bounds.getWidth(), bounds.getHeight()); { unsigned int number = 4; for (int i = 0, j = 0; i < number; ++i) { if (i > 0) verticalLayout.setItemLayout(j++, 0, -1, -1); verticalLayout.setItemLayout(j++, 48, 48, 48); } Component *powerItems[] = { powerOffButton.get(), rebootButton.get(), sleepButton.get() }; auto b = bounds.reduced(10); b.setLeft(70); verticalLayout.layOutComponents(powerItems, 1, b.getX(), b.getY(), b.getWidth(), b.getHeight(), true, true); } mainPage->setBounds(bounds); powerOffButton->setBounds(bounds.getWidth()/7, 40, 350, 40); sleepButton->setBounds(bounds.getWidth()/7, 90, 350, 40); rebootButton->setBounds(bounds.getWidth()/7, 140, 350, 40); felButton->setBounds(bounds.getWidth()/7, 190, 350, 40); backButton->setBounds(bounds.getWidth()-60, bounds.getY(), 60, bounds.getHeight()); buildNameLabel->setBounds(bounds.getX(), bounds.getY(), bounds.getWidth(), 30); buildNameLabel->setBoundsToFit(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(), Justification::centredBottom, true); rev->setBounds(bounds.getX(), bounds.getY(), 100, 30); updateButton->setBounds(bounds.getX()+372, bounds.getY()+5, 100, 30); int width = updateWindow->getWidth(); int height = updateWindow->getHeight(); int x = bounds.getWidth()/2-width/2; int y = bounds.getHeight()/2-height/2; updateWindow->setBounds(bounds.getX()+x, bounds.getY()+y, width, height); }
void PersonalizePageComponent::resized(){ auto bounds = getLocalBounds(); backButton->setBounds(bounds.getX(), bounds.getY(), 60, bounds.getHeight()); background.setBounds(bounds.getX()+70, bounds.getY()+20, 150, 30); icons.setBounds(bounds.getX()+70, bounds.getY()+25+bounds.getHeight()/3, 200, 30); int btn_width = 85; int btn_height = 30; choose_back.setBounds(bounds.getX()+260, bounds.getY()+20, 2*btn_width+20, btn_height); add_btn.setBounds(bounds.getX()+260, bounds.getY()+25+bounds.getHeight()/3, btn_width, btn_height); opt_back.setBounds(bounds.getX()+70, bounds.getY()+70, 150, btn_height); edit_back.setBounds(bounds.getX()+155, bounds.getY()+70, 295, btn_height); int gap = 40; int x = bounds.getX()+70; int y = bounds.getY()+65+bounds.getHeight()/3; Label* labels[3] = {&opt_name, &opt_img, &opt_shell}; TextEditor* fields[3] = {&edit_name, &edit_icn, &edit_shell}; for(int i = 0; i < 3; i++){ int size = 107; int t_width = 75; if(i==2) size = 304; labels[i]->setBounds(x, y, t_width, btn_height); fields[i]->setBounds(x+t_width+5, y, size, btn_height); if(i==0) x += t_width+size+15; else{ x = bounds.getX()+70; y+=gap; } } apply.setBounds(x, y, 385, btn_height); success.setBounds(x+130, y, 385, btn_height); }
void FilterParametersComponent::paint(Graphics & g) { Font panelNameFont = Font(PANEL_NAME_FONT_SIZE, Font::plain).withTypefaceStyle("Italic"); { float x = 0.0f, y = 0.0f, width = (float)getWidth(), height = (float)getHeight(); g.setColour(PANEL_COLOUR); g.fillRoundedRectangle(x, y, width, height, 10.0f); } { Rectangle<int> bounds = getLocalBounds(); Rectangle<int> textArea = bounds.removeFromTop(PANEL_NAME_HEIGHT).reduced(LOCAL_MARGIN); String text("FILTER"); Colour textColour = Colours::white; g.setColour(textColour); g.setFont(panelNameFont); g.drawText(text, textArea, Justification::centred, false); } }
void ConvolutionMatrixComponent::resized() { auto matrix_height = optimum_routing_size * model.get_num_inputs(); auto matrix_width = optimum_routing_size * model.get_num_outputs(); auto input_width = getWidth() - matrix_width; auto bounds = getLocalBounds(); auto left = bounds.removeFromLeft(input_width); auto input_area = left.removeFromTop(matrix_height); hrtf_component.setBounds(left.reduced(4, 4)); auto matrix_area = bounds.removeFromTop(matrix_height); auto output_area = bounds; for (auto i = 0u; i != routings.size(); ++i) { auto y = i * optimum_routing_size; for (auto j = 0u; j != routings[i].size(); ++j) { auto x = j * optimum_routing_size; routings[i][j]->setSize(optimum_routing_size, optimum_routing_size); routings[i][j]->setTopLeftPosition(matrix_area.getTopLeft() + juce::Point<int>(x, y)); } } for (auto i = 0u; i != inputs.size(); ++i) { inputs[i]->setSize(input_area.getWidth(), optimum_routing_size); inputs[i]->setTopLeftPosition( input_area.getTopLeft() + juce::Point<int>(0, i * optimum_routing_size)); } for (auto i = 0u; i != outputs.size(); ++i) { outputs[i]->setSize(optimum_routing_size, output_area.getHeight()); outputs[i]->setTopLeftPosition( output_area.getTopLeft() + juce::Point<int>(i * optimum_routing_size, 0)); } }
/* * compute the path. * the x coordinates will range from 0..1 * the y coordinates will be in phase degrees * */ void PhaseChart::update () { m_isDefined = false; m_path.clear(); if (m_filter) { m_isDefined = true; const Rectangle<int> bounds = getLocalBounds (); const Rectangle<int> r = bounds.reduced (4, 4); for (int xi = 0; xi < r.getWidth(); ++xi ) { float x = xi / float(r.getWidth()); Dsp::complex_t c = m_filter->response (x/2); float y = float (90 * (std::arg(c) / Dsp::doublePi)); if (!Dsp::is_nan (y)) { if (xi == 0) m_path.startNewSubPath (x, y); else m_path.lineTo (x, y); } else { m_path.clear (); m_isDefined = false; break; } } if (m_isDefined) m_path.startNewSubPath (0, 0); } repaint(); }
void JUCESplashScreen::paint (Graphics& g) { auto r = getLocalBounds().toFloat(); Point<float> bottomRight (0.9f * r.getWidth(), 0.9f * r.getHeight()); ColourGradient cg (Colour (0x00000000), Line<float> (0.0f, r.getHeight(), r.getWidth(), 0.0f) .findNearestPointTo (bottomRight), Colour (0xff000000), bottomRight, false); cg.addColour (0.25f, Colour (0x10000000)); cg.addColour (0.50f, Colour (0x30000000)); cg.addColour (0.75f, Colour (0x70000000)); g.setFillType (cg); g.fillAll(); content->drawWithin (g, getLogoArea (r), RectanglePlacement::centred, 1.0f); if (splashDisplayTime == 0) splashDisplayTime = Time::getMillisecondCounter(); if (! isTimerRunning()) startTimer (millisecondsToDisplaySplash); }
void resized() override { Rectangle<int> area (getLocalBounds().reduced (10)); Rectangle<int> row (area.removeFromTop (100)); rotarySlider.setBounds (row.removeFromLeft (100).reduced (5)); verticalSlider.setBounds (row.removeFromLeft (100).reduced (5)); barSlider.setBounds (row.removeFromLeft (100).reduced (5, 25)); incDecSlider.setBounds (row.removeFromLeft (100).reduced (5, 28)); row = area.removeFromTop (100); button1.setBounds (row.removeFromLeft (100).reduced (5)); Rectangle<int> row2 (row.removeFromTop (row.getHeight() / 2).reduced (0, 10)); button2.setBounds (row2.removeFromLeft (100).reduced (5, 0)); button3.setBounds (row2.removeFromLeft (100).reduced (5, 0)); button4.setBounds (row2.removeFromLeft (100).reduced (5, 0)); row2 = (row.removeFromTop (row2.getHeight() + 20).reduced (5, 10)); for (int i = 0; i < radioButtons.size(); ++i) radioButtons.getUnchecked (i)->setBounds (row2.removeFromLeft (100)); }
void PageStackComponent::transitionIn(Component *component, Transition transition, int durationMillis, bool reverse) { addAndMakeVisible(component); auto bounds = getLocalBounds(); switch (transition) { case kTransitionTranslateHorizontal: { float dir = reverse ? -1.0f : 1.0f; component->setBounds(bounds.translated(bounds.getWidth() * dir, 0)); animateTranslation(component, 0, 0, 1.0f, durationMillis); break; } case kTransitionTranslateHorizontalLeft: { float dir = reverse ? 1.0f : -1.0f; component->setBounds(bounds.translated(bounds.getWidth() * dir, 0)); animateTranslation(component, 0, 0, 1.0f, durationMillis); } break; default: { component->setBounds(bounds); component->setVisible(true); } } component->setEnabled(true); }
Rectangle<float> DrawableButton::getImageBounds() const { Rectangle<int> r (getLocalBounds()); if (style != ImageStretched) { int indentX = jmin (edgeIndent, proportionOfWidth (0.3f)); int indentY = jmin (edgeIndent, proportionOfHeight (0.3f)); if (style == ImageOnButtonBackground) { indentX = jmax (getWidth() / 4, indentX); indentY = jmax (getHeight() / 4, indentY); } else if (style == ImageAboveTextLabel) { r = r.withTrimmedBottom (jmin (16, proportionOfHeight (0.25f))); } r = r.reduced (indentX, indentY); } return r.toFloat(); }
//====================================================================== void HeaderComponent::resized() { auto bounds = getLocalBounds(); configLabel.setFont ({ bounds.getHeight() / 3.0f }); //====================================================================== { auto headerBounds = bounds.removeFromLeft (tabsWidth); const int buttonSize = 25; auto buttonBounds = headerBounds.removeFromRight (buttonSize); projectSettingsButton->setBounds (buttonBounds.removeFromBottom (buttonSize).reduced (2)); juceIcon->setBounds (headerBounds.removeFromLeft (headerBounds.getHeight()).reduced (2)); headerBounds.removeFromRight (5); projectNameLabel.setBounds (headerBounds); } //====================================================================== auto exporterWidth = jmin (400, bounds.getWidth() / 2); Rectangle<int> exporterBounds (0, 0, exporterWidth, bounds.getHeight()); exporterBounds.setCentre (bounds.getCentre()); runAppButton->setBounds (exporterBounds.removeFromRight (exporterBounds.getHeight()).reduced (2)); saveAndOpenInIDEButton->setBounds (exporterBounds.removeFromRight (exporterBounds.getHeight()).reduced (2)); exporterBounds.removeFromRight (5); exporterBox.setBounds (exporterBounds.removeFromBottom (roundToInt (exporterBounds.getHeight() / 1.8f))); configLabel.setBounds (exporterBounds); bounds.removeFromRight (5); userSettingsButton->setBounds (bounds.removeFromRight (bounds.getHeight()).reduced (2)); }
void LivePropertyEditorBase::resized() { Rectangle<int> r (getLocalBounds().reduced (0, 3).withTrimmedBottom (1)); Rectangle<int> left (r.removeFromLeft (jmax (200, r.getWidth() / 3))); Rectangle<int> top (left.removeFromTop (25)); resetButton.setBounds (top.removeFromRight (35).reduced (0, 3)); name.setBounds (top); if (customComp != nullptr) { valueEditor.setBounds (left.removeFromTop (25)); left.removeFromTop (2); customComp->setBounds (left); } else { valueEditor.setBounds (left); } r.removeFromLeft (4); sourceEditor.setBounds (r); }
void resized() { const int buttonHeight = 26; Rectangle<int> area (getLocalBounds()); getLookAndFeel().createFileChooserHeaderText (getName(), instructions, text, getWidth()); const Rectangle<float> bb (text.getBoundingBox (0, text.getNumGlyphs(), false)); area.removeFromTop (roundToInt (bb.getBottom()) + 10); chooserComponent.setBounds (area.removeFromTop (area.getHeight() - buttonHeight - 20)); Rectangle<int> buttonArea (area.reduced (16, 10)); okButton.changeWidthToFitText (buttonHeight); okButton.setBounds (buttonArea.removeFromRight (okButton.getWidth() + 16)); buttonArea.removeFromRight (16); cancelButton.changeWidthToFitText (buttonHeight); cancelButton.setBounds (buttonArea.removeFromRight (cancelButton.getWidth())); newFolderButton.changeWidthToFitText (buttonHeight); newFolderButton.setBounds (buttonArea.removeFromLeft (newFolderButton.getWidth())); }
AffineTransform PhaseChart::calcTransform () { const Rectangle<int> bounds = getLocalBounds (); const Rectangle<int> r = bounds.reduced (4, 4); AffineTransform t; // scale x from 0..1 to 0..getWidth(), and flip vertical t = AffineTransform::scale (float(r.getWidth()), -1.f); // move y down so 120 is at the top t = t.translated (0.f, 120.f); // scale y from phase to 0..1 bounds in r t = t.scaled (1.f, 1.f/(maxPhase - -maxPhase)); // scale y from 0..1 to getHeight() t = t.scaled (1.f, float(r.getHeight())); // translate t = t.translated (float(r.getX()), float(r.getY())); return t; }
void ParamGraph::paint (Graphics& g){ //Clear the background g.fillAll (Colours::black); Rectangle<int> bounds = getLocalBounds(); //Draw axes g.setColour(Colours::white); g.drawLine(0, bounds.getHeight() - axisspacing, bounds.getWidth(), bounds.getHeight() - axisspacing); g.drawLine(axisspacing, 0, axisspacing, bounds.getHeight()); g.setFont(axisspacing); g.drawSingleLineText("0", 3, bounds.getHeight() - 2); float n = (float)core.getNumFilters(); float lastval, thisval; lastval = mode ? core.getBWValue(0) : core.getCtrValue(0); float maxy = mode ? core.getMaxBW() : core.getMaxCtr(); //Scale float axisstep = getScaleDivisions(n, 10); int x; for(float i=axisstep; i<n; i+=axisstep){ x = axisspacing + ((bounds.getWidth() - axisspacing) * (i-1.0f) / (n-1.0f)); g.drawSingleLineText(String(i), x - (4 * (int)log10(i)) - 2, bounds.getHeight() - 2); g.drawLine(x, bounds.getHeight() - axisspacing + 1, x, bounds.getHeight() - axisspacing - 2); } //Data for(int i=1; i<n; ++i){ thisval = mode ? core.getBWValue(i) : core.getCtrValue(i); g.drawLine(axisspacing + ((bounds.getWidth() - axisspacing) * (i-1) / (n-1)), bounds.getHeight() - (axisspacing + ((bounds.getHeight() - axisspacing) * lastval / maxy)), axisspacing + ((bounds.getWidth() - axisspacing) * i / (n-1)), bounds.getHeight() - (axisspacing + ((bounds.getHeight() - axisspacing) * thisval / maxy))); lastval = thisval; } }
void resized() { Component* const c = getChildComponent(0); if (c != nullptr) c->setBounds (getLocalBounds()); }
void StateMachineView::resized() { BaseManagerViewUI::resized(); stmUI->setBounds(getLocalBounds()); }
void resized() { if (customComponent != nullptr) customComponent->setBounds (getLocalBounds()); }
void TabbedButtonBar::resized() { int depth = getWidth(); int length = getHeight(); if (orientation == TabsAtTop || orientation == TabsAtBottom) std::swap (depth, length); const int overlap = getLookAndFeel().getTabButtonOverlap (depth) + getLookAndFeel().getTabButtonSpaceAroundImage() * 2; int i, totalLength = overlap; int numVisibleButtons = tabs.size(); for (i = 0; i < tabs.size(); ++i) { TabBarButton* const tb = tabs.getUnchecked(i)->component; totalLength += tb->getBestTabLength (depth) - overlap; tb->overlapPixels = overlap / 2; } double scale = 1.0; if (totalLength > length) scale = jmax (minimumScale, length / (double) totalLength); const bool isTooBig = totalLength * scale > length; int tabsButtonPos = 0; if (isTooBig) { if (extraTabsButton == nullptr) { addAndMakeVisible (extraTabsButton = getLookAndFeel().createTabBarExtrasButton()); extraTabsButton->addListener (behindFrontTab); extraTabsButton->setAlwaysOnTop (true); extraTabsButton->setTriggeredOnMouseDown (true); } const int buttonSize = jmin (proportionOfWidth (0.7f), proportionOfHeight (0.7f)); extraTabsButton->setSize (buttonSize, buttonSize); if (orientation == TabsAtTop || orientation == TabsAtBottom) { tabsButtonPos = getWidth() - buttonSize / 2 - 1; extraTabsButton->setCentrePosition (tabsButtonPos, getHeight() / 2); } else { tabsButtonPos = getHeight() - buttonSize / 2 - 1; extraTabsButton->setCentrePosition (getWidth() / 2, tabsButtonPos); } totalLength = 0; for (i = 0; i < tabs.size(); ++i) { TabBarButton* const tb = tabs.getUnchecked(i)->component; const int newLength = totalLength + tb->getBestTabLength (depth); if (i > 0 && newLength * minimumScale > tabsButtonPos) { totalLength += overlap; break; } numVisibleButtons = i + 1; totalLength = newLength - overlap; } scale = jmax (minimumScale, tabsButtonPos / (double) totalLength); } else { extraTabsButton = nullptr; } int pos = 0; TabBarButton* frontTab = nullptr; for (i = 0; i < tabs.size(); ++i) { TabBarButton* const tb = getTabButton (i); if (tb != nullptr) { const int bestLength = roundToInt (scale * tb->getBestTabLength (depth)); if (i < numVisibleButtons) { if (orientation == TabsAtTop || orientation == TabsAtBottom) tb->setBounds (pos, 0, bestLength, getHeight()); else tb->setBounds (0, pos, getWidth(), bestLength); tb->toBack(); if (i == currentTabIndex) frontTab = tb; tb->setVisible (true); } else { tb->setVisible (false); } pos += bestLength - overlap; } } behindFrontTab->setBounds (getLocalBounds()); if (frontTab != nullptr) { frontTab->toFront (false); behindFrontTab->toBehind (frontTab); } }
FloatRect Shape::getGlobalBounds() const { return getTransform().transformRect(getLocalBounds()); }
sf::FloatRect getGlobalBounds() const noexcept { return getTransform().transformRect(getLocalBounds()); }
sf::FloatRect Animation::getGlobalBounds() const { return getTransform().transformRect(getLocalBounds()); }
void resized() override { scrollbar.setBounds (getLocalBounds().removeFromBottom (14).reduced (2)); }
void ParamView::resized() { panel.setBounds (getLocalBounds().reduced (4)); }