paulxstretch/Source/GenericItemChooser.cpp

355 lines
9.7 KiB
C++

// SPDX-License-Identifier: GPLv3-or-later WITH Appstore-exception
// Copyright (C) 2020 Jesse Chappell
#include "GenericItemChooser.h"
enum {
nameTextColourId = 0x1002830,
currentNameTextColourId = 0x1002850,
selectedColourId = 0x1002840,
separatorColourId = 0x1002860,
disabledColourId = 0x1002870
};
CallOutBox& GenericItemChooser::launchPopupChooser(const Array<GenericItemChooserItem> & items, Rectangle<int> targetBounds, Component * targetComponent, GenericItemChooser::Listener * listener, int tag, int selectedIndex, int maxheight, bool dismissSel)
{
auto chooser = std::make_unique<GenericItemChooser>(items, tag);
chooser->dismissOnSelected = dismissSel;
if (selectedIndex >= 0) {
chooser->setCurrentRow(selectedIndex);
}
if (listener) {
chooser->addListener(listener);
}
if (maxheight > 0) {
chooser->setMaxHeight(maxheight);
}
CallOutBox & box = CallOutBox::launchAsynchronously (std::move(chooser), targetBounds, targetComponent);
box.setDismissalMouseClicksAreAlwaysConsumed(true);
// box.setArrowSize(0);
box.grabKeyboardFocus();
return box;
}
CallOutBox& GenericItemChooser::launchPopupChooser(const Array<GenericItemChooserItem> & items, juce::Rectangle<int> targetBounds, Component * targetComponent, std::function<void (GenericItemChooser* chooser,int index)> onSelectedFunction, int selectedIndex, int maxheight, bool dismissSel)
{
auto chooser = std::make_unique<GenericItemChooser>(items, 0);
chooser->dismissOnSelected = dismissSel;
if (selectedIndex >= 0) {
chooser->setCurrentRow(selectedIndex);
}
chooser->onSelected = onSelectedFunction;
if (maxheight > 0) {
chooser->setMaxHeight(maxheight);
}
CallOutBox & box = CallOutBox::launchAsynchronously (std::move(chooser), targetBounds, targetComponent);
box.setDismissalMouseClicksAreAlwaysConsumed(true);
// box.setArrowSize(0);
box.grabKeyboardFocus();
return box;
}
GenericItemChooser::GenericItemChooser(const Array<GenericItemChooserItem> & items_, int tag_) : font (16.0, Font::plain), catFont(15.0, Font::plain), items(items_), tag(tag_)
{
currentIndex = -1;
#if JUCE_IOS || JUCE_ANDROID
rowHeight = 42;
#else
rowHeight = 32;
#endif
numRows = items.size();
// Create our table component and add it to this component..
addAndMakeVisible (table);
table.setModel (this);
// give it a border
table.setColour (ListBox::outlineColourId, Colour::fromFloatRGBA(0.0, 0.0, 0.0, 0.0));
table.setColour (ListBox::backgroundColourId, Colour::fromFloatRGBA(0.1, 0.1, 0.1, 1.0f));
table.setColour (ListBox::textColourId, Colours::whitesmoke.withAlpha(0.8f));
setColour (nameTextColourId, Colour::fromFloatRGBA(1.0f, 1.0f, 1.0f, 0.8f));
setColour (currentNameTextColourId, Colour::fromFloatRGBA(0.4f, 0.8f, 1.0f, 0.9f));
setColour (selectedColourId, Colour (0xff3d70c8).withAlpha(0.5f));
setColour (separatorColourId, Colour::fromFloatRGBA(1.0f, 1.0f, 1.0f, 0.5f));
setColour (disabledColourId, Colour::fromFloatRGBA(0.7f, 0.7f, 0.7f, 0.7f));
table.setOutlineThickness (0);
//table.getViewport()->setScrollOnDragEnabled(true);
table.getViewport()->setScrollBarsShown(true, false);
table.getViewport()->setScrollOnDragEnabled(true);
table.setRowSelectedOnMouseDown(true);
table.setRowClickedOnMouseDown(false);
table.setMultipleSelectionEnabled (false);
table.setRowHeight(rowHeight);
int newh = (rowHeight) * numRows + 4;
setSize(getAutoWidth(), newh);
}
GenericItemChooser::~GenericItemChooser()
{
}
void GenericItemChooser::setCurrentRow(int index)
{
currentIndex = index;
SparseSet<int> selrows;
selrows.addRange(Range<int>(index,index+1));
table.setSelectedRows(selrows);
table.updateContent();
}
void GenericItemChooser::setItems(const Array<GenericItemChooserItem> & items_)
{
items = items_;
numRows = items.size();
table.updateContent();
int newh = (rowHeight) * numRows;
setSize(getAutoWidth(), newh);
}
int GenericItemChooser::getAutoWidth()
{
int targw = 60;
for (int i=0; i < items.size(); ++i) {
int tsize = font.getStringWidth(items[i].name);
if (items[i].image.isValid()) {
tsize += rowHeight - 8;
}
targw = jmax(targw, tsize);
}
return targw + 30;
}
void GenericItemChooser::setRowHeight(int ht)
{
rowHeight = ht;
table.setRowHeight(rowHeight);
int newh = (rowHeight+2) * numRows;
if (maxHeight > 0) {
newh = jmin(newh, maxHeight);
}
setSize(getAutoWidth(), newh);
}
void GenericItemChooser::setMaxHeight(int ht)
{
maxHeight = ht;
int newh = (rowHeight+2) * numRows;
if (maxHeight > 0) {
newh = jmin(newh, maxHeight);
}
setSize(getAutoWidth(), newh);
}
// This is overloaded from TableListBoxModel, and must return the total number of rows in our table
int GenericItemChooser::getNumRows()
{
return numRows;
}
String GenericItemChooser::getNameForRow (int rowNumber)
{
if (rowNumber< items.size()) {
return items[rowNumber].name;
}
return ListBoxModel::getNameForRow(rowNumber);
}
void GenericItemChooser::listBoxItemClicked (int rowNumber, const MouseEvent& e)
{
DBG("listbox clicked");
if (items[rowNumber].disabled) {
// not selectable
return;
}
listeners.call (&GenericItemChooser::Listener::genericItemChooserSelected, this, rowNumber);
if (onSelected) {
onSelected(this, rowNumber);
}
if (dismissOnSelected) {
if (CallOutBox* const cb = findParentComponentOfClass<CallOutBox>()) {
cb->dismiss();
}
} else {
setCurrentRow(rowNumber);
repaint();
}
}
void GenericItemChooser::selectedRowsChanged(int lastRowSelected)
{
// notify listeners
DBG("Selected rows changed");
}
void GenericItemChooser::deleteKeyPressed (int)
{
DBG("delete key pressed");
}
void GenericItemChooser::returnKeyPressed (int rowNumber)
{
DBG("return key pressed: " << rowNumber);
listeners.call (&GenericItemChooser::Listener::genericItemChooserSelected, this, rowNumber);
if (rowNumber < items.size() && items[rowNumber].disabled) {
// not selectable
return;
}
if (onSelected) {
onSelected(this, rowNumber);
}
if (dismissOnSelected) {
if (CallOutBox* const cb = findParentComponentOfClass<CallOutBox>()) {
cb->giveAwayKeyboardFocus();
cb->dismiss();
}
} else {
setCurrentRow(rowNumber);
repaint();
}
}
void GenericItemChooser::paintListBoxItem (int rowNumber, Graphics &g, int width, int height, bool rowIsSelected)
{
if (items[rowNumber].separator) {
g.setColour (findColour(separatorColourId));
g.drawLine(0, 0, width, 0);
}
if (rowIsSelected && !items[rowNumber].disabled) {
g.setColour (findColour(selectedColourId));
g.fillRect(Rectangle<int>(0,0,width,height));
}
if (items[rowNumber].disabled) {
g.setColour (findColour(disabledColourId));
}
else if (rowNumber == currentIndex) {
g.setColour (findColour(currentNameTextColourId));
}
else {
g.setColour (findColour(nameTextColourId));
}
g.setFont (font);
int imagewidth = 0;
if (rowNumber < items.size()) {
if (items[rowNumber].image.isValid()) {
imagewidth = height-8;
//g.drawImage(items[rowNumber].image, Rectangle<float>(2, 2, imagewidth, height - 4));
g.drawImageWithin(items[rowNumber].image, 2, 4, imagewidth, imagewidth, RectanglePlacement(RectanglePlacement::centred|RectanglePlacement::onlyReduceInSize));
}
}
/*
int imagewidth = height * 0.75;
if (rowNumber == 0) {
g.drawImageWithin(wheelImage, 2, 2, imagewidth, height - 4, RectanglePlacement::centred|RectanglePlacement::onlyReduceInSize);
}
else if (rowNumber == 1) {
g.drawImageWithin(stringImage, 2, 2, imagewidth, height - 4, RectanglePlacement::centred|RectanglePlacement::onlyReduceInSize);
}
else {
g.drawImageWithin(keyboardImage, 2, 2, imagewidth, height - 4, RectanglePlacement::centred|RectanglePlacement::onlyReduceInSize);
}
*/
String text = items[rowNumber].name;
//DBG("Paint " << text);
//g.drawFittedText (text, imagewidth + 10, 0, width - (imagewidth+8), height, Justification::centredLeft, 1, 0.5);
g.drawFittedText (text, imagewidth + 8, 0, width - (imagewidth+8), height, Justification::centredLeft, 1, 0.5);
}
void GenericItemChooser::buttonClicked (Button* buttonThatWasClicked)
{
//AppState * app = AppState::getInstance();
}
void GenericItemChooser::paint (Graphics& g)
{
//g.fillAll (Colour (0xff000000));
}
//==============================================================================
void GenericItemChooser::resized()
{
// position our table with a gap around its edge
int keywidth = 50;
int bottomButtHeight = 40;
table.setBoundsInset (BorderSize<int>(2,2,2,2));
// table.setTouchScrollScale(1.0f / AppState::getInstance()->scaleFactor);
//int bottbuttwidth = (int) (0.3333f * (getWidth()-keywidth));
//int addbuttwidth = (getWidth()-keywidth) - 2*bottbuttwidth - 8;
//allButton->setBounds(keywidth+2, getHeight()-bottomButtHeight-4, bottbuttwidth, bottomButtHeight);
//favsButton->setBounds(keywidth+2+bottbuttwidth, getHeight()-bottomButtHeight-4, bottbuttwidth, bottomButtHeight);
//addFavButton->setBounds(getWidth()-addbuttwidth-4, getHeight()-bottomButtHeight-4, addbuttwidth, bottomButtHeight);
}