I am implementing a new class that acts in a similar way to ComboBox. For each item there is an additional String variable (stored in ItemInfo). Since I basically want the same function as ComboBox I will inherit it and add the code I need.
This is the header file.
class BluetoothComboBox : public ComboBox
{
public:
explicit BluetoothComboBox (const String& componentName = String());
~BluetoothComboBox(); // TODO
void addItem (const String& newItemText, const String& newItemMAC, const int newItemId);
private:
//==============================================================================
struct ItemInfo
{
ItemInfo (const String&, const String&, int itemId, bool isEnabled, bool isHeading);
bool isSeparator() const noexcept;
bool isRealItem() const noexcept;
String name; String macAddress; int itemId; bool isEnabled : 1, isHeading : 1; };
enum EditableState { editableUnknown, labelIsNotEditable, labelIsEditable };
OwnedArray<ItemInfo> items; String name; Value currentId; int lastCurrentId; bool isButtonDown, separatorPending, menuActive, scrollWheelEnabled; float mouseWheelAccumulator; ListenerList<Listener> listeners; ScopedPointer<Label> label; String textWhenNothingSelected, noChoicesMessage; EditableState labelEditableState;
ItemInfo* getItemForId (int) const noexcept; ItemInfo* getItemForIndex (int) const noexcept; bool selectIfEnabled (int index); bool nudgeSelectedItem (int delta); void sendChange (NotificationType); void showPopupIfNotActive();
};
And the .cpp file.
#include “BluetoothComboBox.h”
BluetoothComboBox::ItemInfo::ItemInfo (const String& nm, const String& mac, int iid, bool enabled, bool heading)
: name (nm), macAddress (mac), itemId (iid), isEnabled (enabled), isHeading (heading)
{
}
bool BluetoothComboBox::ItemInfo::isSeparator() const noexcept
{
return name.isEmpty();
}
bool BluetoothComboBox::ItemInfo::isRealItem() const noexcept
{
return ! (isHeading || name.isEmpty());
}
//==============================================================================
BluetoothComboBox::BluetoothComboBox (const String& name)
: Component (name),
lastCurrentId (0),
isButtonDown (false),
separatorPending (false),
menuActive (false),
scrollWheelEnabled (false),
mouseWheelAccumulator (0),
noChoicesMessage (TRANS(“(no choices)”)),
labelEditableState (editableUnknown)
{
ComboBox::setRepaintsOnMouseActivity (true);
ComboBox::lookAndFeelChanged();
currentId.addListener (this);
}
BluetoothComboBox::~BluetoothComboBox()
{
currentId.removeListener (this);
hidePopup();
label = nullptr;
}
//==============================================================================
void BluetoothComboBox::addItem (const String& newItemText, const String& newItemMAC, const int newItemId)
{
// you can’t add empty strings to the list…
jassert (newItemText.isNotEmpty());
// you can't add empty strings to the list.. jassert (newItemMAC.isNotEmpty());
// IDs must be non-zero, as zero is used to indicate a lack of selecion. jassert (newItemId != 0);
// you shouldn't use duplicate item IDs! jassert (getItemForId (newItemId) == nullptr);
if (newItemText.isNotEmpty() && newItemId != 0) { if (separatorPending) { separatorPending = false; items.add (new ItemInfo (String(), String(), 0, false, false)); }
items.add (new ItemInfo (newItemText, newItemMAC, newItemId, true, false)); }
}
//==============================================================================
BluetoothComboBox::ItemInfo* BluetoothComboBox::getItemForId (const int itemId) const noexcept
{
if (itemId != 0)
{
for (int i = items.size(); --i >= 0;)
if (items.getUnchecked(i)->itemId == itemId)
return items.getUnchecked(i);
}
return nullptr;
}
BluetoothComboBox::ItemInfo* BluetoothComboBox::getItemForIndex (const int index) const noexcept
{
for (int n = 0, i = 0; i < items.size(); ++i)
{
ItemInfo* const item = items.getUnchecked(i);
if (item->isRealItem()) if (n++ == index) return item; }
return nullptr;
}
bool BluetoothComboBox::selectIfEnabled (const int index)
{
if (const ItemInfo* const item = getItemForIndex (index))
{
if (item->isEnabled)
{
setSelectedItemIndex (index);
return true;
}
}
return false;
}
bool BluetoothComboBox::nudgeSelectedItem (int delta)
{
for (int i = getSelectedItemIndex() + delta; isPositiveAndBelow (i, getNumItems()); i += delta)
if (selectIfEnabled (i))
return true;
return false;
}
void BluetoothComboBox::showPopupIfNotActive()
{
if (! menuActive)
{
menuActive = true;
showPopup();
}
}
I do feel rather silly copying the code from ComboBox only to add this one additional variable to ItemInfo, but this is the best idea I have had so for. When I compile this code I however get the following compile error:
…/…/Source/BluetoothComboBox.cpp: In constructor ‘BluetoothComboBox::BluetoothComboBox(const juce::String&)’:
…/…/Source/BluetoothComboBox.cpp:31:7: error: type ‘juce::Component’ is not a direct base of ‘BluetoothComboBox’
: Component (name),
How would I go about solving this kind of error? Also, this is surely not the best way to accomplish such a simple task; do the programming wizards here have a better solution?