finalcut/src/fbuttongroup.cpp

630 lines
12 KiB
C++
Raw Normal View History

// File: fbuttongroup.cpp
// Provides: class FButtonGroup
2015-05-23 13:35:12 +02:00
#include "fapp.h"
#include "fbuttongroup.h"
#include "fstatusbar.h"
#include "ftogglebutton.h"
//----------------------------------------------------------------------
// class FButtonGroup
//----------------------------------------------------------------------
// constructor and destructor
//----------------------------------------------------------------------
2015-09-22 04:18:20 +02:00
FButtonGroup::FButtonGroup(FWidget* parent)
: FWidget(parent)
, text()
, border(true)
, buttonlist()
2015-05-23 13:35:12 +02:00
{
2015-09-22 04:18:20 +02:00
init();
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
2015-09-22 04:18:20 +02:00
FButtonGroup::FButtonGroup (const FString& txt, FWidget* parent)
: FWidget(parent)
, text(txt)
, border(true)
, buttonlist()
2015-05-23 13:35:12 +02:00
{
2015-09-22 04:18:20 +02:00
init();
2015-05-23 13:35:12 +02:00
setText(txt);
}
//----------------------------------------------------------------------
FButtonGroup::~FButtonGroup() // destructor
{
FButtonList::iterator iter;
2015-05-23 13:35:12 +02:00
if ( buttonlist.empty() )
return;
iter = buttonlist.begin();
while ( iter != buttonlist.end() )
{
(*iter)->setGroup(0);
iter = buttonlist.erase(iter);
}
}
// public methods of FButtonGroup
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
FToggleButton* FButtonGroup::getFirstButton()
2015-05-23 13:35:12 +02:00
{
if ( buttonlist.empty() )
return 0;
2015-05-23 13:35:12 +02:00
FButtonList::const_iterator iter, end;
iter = buttonlist.begin();
end = buttonlist.end();
2015-05-23 13:35:12 +02:00
while ( iter != end )
{
if ( (*iter)->isEnabled() && (*iter)->acceptFocus() )
return (*iter);
2015-05-23 13:35:12 +02:00
++iter;
}
return 0;
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
FToggleButton* FButtonGroup::getLastButton()
2015-05-23 13:35:12 +02:00
{
if ( buttonlist.empty() )
return 0;
FButtonList::const_iterator iter, begin;
begin = buttonlist.begin();
iter = buttonlist.end();
do
{
--iter;
if ( (*iter)->isEnabled() && (*iter)->acceptFocus() )
return (*iter);
2015-05-23 13:35:12 +02:00
}
while ( iter != begin );
2015-05-23 13:35:12 +02:00
return 0;
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
bool FButtonGroup::setEnable (bool on)
2015-05-23 13:35:12 +02:00
{
FWidget::setEnable(on);
if ( on )
{
flags |= fc::active;
setHotkeyAccelerator();
}
else
{
flags &= ~fc::active;
delAccelerator();
}
return on;
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
bool FButtonGroup::setBorder(bool on)
2015-05-23 13:35:12 +02:00
{
if ( on )
border = true;
else
border = false;
2015-05-23 13:35:12 +02:00
return on;
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
void FButtonGroup::setText (const FString& txt)
2015-05-23 13:35:12 +02:00
{
text = txt;
2015-05-23 13:35:12 +02:00
if ( isEnabled() )
2015-05-23 13:35:12 +02:00
{
2015-11-12 01:33:16 +01:00
delAccelerator();
setHotkeyAccelerator();
}
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
bool FButtonGroup::hasFocusedButton()
2015-05-23 13:35:12 +02:00
{
if ( buttonlist.empty() )
return false;
2015-05-23 13:35:12 +02:00
FButtonList::const_iterator iter, end;
iter = buttonlist.begin();
end = buttonlist.end();
2015-05-23 13:35:12 +02:00
while ( iter != end )
2015-05-23 13:35:12 +02:00
{
if ( (*iter)->hasFocus() )
return true;
++iter;
2015-05-23 13:35:12 +02:00
}
return false;
}
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
bool FButtonGroup::hasCheckedButton()
{
if ( buttonlist.empty() )
return false;
2015-05-23 13:35:12 +02:00
FButtonList::const_iterator iter, end;
iter = buttonlist.begin();
end = buttonlist.end();
2015-05-23 13:35:12 +02:00
while ( iter != end )
2015-05-23 13:35:12 +02:00
{
if ( (*iter)->isChecked() )
return true;
++iter;
2015-05-23 13:35:12 +02:00
}
return false;
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
void FButtonGroup::hide()
{
int size;
short fg, bg;
2015-05-23 13:35:12 +02:00
char* blank;
FWidget::hide();
FWidget* parent_widget = getParentWidget();
2015-05-23 13:35:12 +02:00
if ( ! buttonlist.empty() )
{
FButtonList::const_iterator iter, end;
2015-05-23 13:35:12 +02:00
iter = buttonlist.begin();
end = buttonlist.end();
while ( iter != end )
{
(*iter)->hide();
++iter;
}
}
if ( parent_widget )
{
fg = parent_widget->getForegroundColor();
bg = parent_widget->getBackgroundColor();
}
else
{
fg = wc.dialog_fg;
bg = wc.dialog_bg;
}
2015-05-23 13:35:12 +02:00
setColor (fg, bg);
size = getWidth();
if ( size < 0 )
return;
2015-05-23 13:35:12 +02:00
blank = new char[size+1];
std::memset(blank, ' ', uLong(size));
2015-05-23 13:35:12 +02:00
blank[size] = '\0';
for (int y=0; y < getHeight(); y++)
2015-05-23 13:35:12 +02:00
{
setPrintPos (1, 1+y);
2015-05-23 13:35:12 +02:00
print (blank);
}
2015-05-23 13:35:12 +02:00
delete[] blank;
}
//----------------------------------------------------------------------
2015-12-21 18:48:38 +01:00
void FButtonGroup::insert (FToggleButton* button)
2015-05-23 13:35:12 +02:00
{
if ( ! button )
return;
if ( button->getGroup() )
button->getGroup()->remove(button);
2015-05-23 13:35:12 +02:00
// setChecked the first FRadioButton
if ( buttonlist.size() == 1 && isRadioButton(*buttonlist.begin()) )
(*buttonlist.begin())->setChecked();
button->setGroup(this);
buttonlist.push_back(button);
button->addCallback
(
"toggled",
_METHOD_CALLBACK (this, &FButtonGroup::cb_buttonToggled)
2015-05-23 13:35:12 +02:00
);
}
//----------------------------------------------------------------------
2015-12-21 18:48:38 +01:00
void FButtonGroup::remove (FToggleButton* button)
2015-05-23 13:35:12 +02:00
{
FButtonList::iterator iter;
2015-05-23 13:35:12 +02:00
if ( ! button || buttonlist.empty() )
2015-05-23 13:35:12 +02:00
return;
iter = buttonlist.begin();
while ( iter != buttonlist.end() )
{
if ( (*iter) == button )
{
iter = buttonlist.erase(iter);
button->setGroup(0);
button->delCallback(this);
break;
}
else
++iter;
}
}
//----------------------------------------------------------------------
2015-09-20 05:44:50 +02:00
void FButtonGroup::onMouseDown (FMouseEvent* ev)
2015-05-23 13:35:12 +02:00
{
2016-01-17 02:57:08 +01:00
if ( ev->getButton() != fc::LeftButton )
2015-05-23 13:35:12 +02:00
return;
2015-05-23 13:35:12 +02:00
directFocus();
}
//----------------------------------------------------------------------
void FButtonGroup::onAccel (FAccelEvent*)
{
directFocus();
}
//----------------------------------------------------------------------
void FButtonGroup::onFocusIn (FFocusEvent* in_ev)
{
if ( hasCheckedButton() && ! buttonlist.empty() )
{
FButtonList::const_iterator iter, end;
2015-05-23 13:35:12 +02:00
iter = buttonlist.begin();
end = buttonlist.end();
while ( iter != end )
{
if ( (*iter)->isChecked() )
{
if ( isRadioButton(*iter) )
{
in_ev->ignore();
FWidget* prev_element = getFocusWidget();
(*iter)->setFocus();
if ( prev_element )
prev_element->redraw();
2015-05-23 13:35:12 +02:00
(*iter)->redraw();
}
2015-05-23 13:35:12 +02:00
break;
}
2015-05-23 13:35:12 +02:00
++iter;
}
}
2015-05-23 13:35:12 +02:00
if ( in_ev->isAccepted() )
{
2016-01-17 02:57:08 +01:00
if ( in_ev->getFocusType() == fc::FocusNextWidget )
2015-05-23 13:35:12 +02:00
{
in_ev->ignore();
FWidget* prev_element = getFocusWidget();
focusFirstChild();
if ( prev_element )
prev_element->redraw();
if ( getFocusWidget() )
getFocusWidget()->redraw();
2015-05-23 13:35:12 +02:00
}
2016-01-17 02:57:08 +01:00
else if ( in_ev->getFocusType() == fc::FocusPreviousWidget )
2015-05-23 13:35:12 +02:00
{
in_ev->ignore();
FWidget* prev_element = getFocusWidget();
focusLastChild();
if ( prev_element )
prev_element->redraw();
if ( getFocusWidget() )
getFocusWidget()->redraw();
2015-05-23 13:35:12 +02:00
}
}
if ( getStatusBar() )
2015-05-23 13:35:12 +02:00
{
getStatusBar()->drawMessage();
2015-05-23 13:35:12 +02:00
updateTerminal();
flush_out();
}
}
//----------------------------------------------------------------------
void FButtonGroup::onFocusOut (FFocusEvent*)
2015-09-22 04:18:20 +02:00
{ }
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
void FButtonGroup::cb_buttonToggled (FWidget* widget, void*)
2015-05-23 13:35:12 +02:00
{
FToggleButton* button = static_cast<FToggleButton*>(widget);
FButtonList::const_iterator iter, end;
2015-05-23 13:35:12 +02:00
if ( ! button->isChecked() )
return;
if ( buttonlist.empty() )
return;
iter = buttonlist.begin();
end = buttonlist.end();
while ( iter != end )
2015-05-23 13:35:12 +02:00
{
if ( (*iter) != button
&& (*iter)->isChecked()
&& isRadioButton(*iter) )
{
(*iter)->unsetChecked();
if ( (*iter)->isVisible() && (*iter)->isShown() )
(*iter)->redraw();
}
++iter;
2015-05-23 13:35:12 +02:00
}
}
// protected methods of FButtonGroup
//----------------------------------------------------------------------
uChar FButtonGroup::getHotkey()
{
uInt length;
if ( text.isEmpty() )
return 0;
length = text.getLength();
for (uInt i=0; i < length; i++)
2015-05-23 13:35:12 +02:00
{
try
{
if ( (i+1 < length) && (text[i] == '&') )
return uChar(text[++i]);
}
catch (const std::out_of_range&)
{
return 0;;
}
2015-05-23 13:35:12 +02:00
}
return 0;
}
//----------------------------------------------------------------------
void FButtonGroup::setHotkeyAccelerator()
{
int hotkey = getHotkey();
if ( hotkey )
{
if ( std::isalpha(hotkey) || std::isdigit(hotkey) )
{
addAccelerator (std::tolower(hotkey));
addAccelerator (std::toupper(hotkey));
// Meta + hotkey
addAccelerator (fc::Fmkey_meta + std::tolower(hotkey));
}
else
addAccelerator (getHotkey());
}
else
delAccelerator();
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
void FButtonGroup::draw()
2015-05-23 13:35:12 +02:00
{
if ( isMonochron() )
setReverse(true);
setColor();
if ( border )
drawBorder();
drawLabel();
if ( isMonochron() )
setReverse(false);
}
//----------------------------------------------------------------------
void FButtonGroup::drawLabel()
{
wchar_t* LabelText;
register wchar_t* src;
register wchar_t* dest;
FString txt;
uInt length;
int hotkeypos;
bool isActive, isNoUnderline;
if ( text.isNull() || text.isEmpty() )
return;
txt = " " + text + " ";
length = txt.getLength();
hotkeypos = -1;
LabelText = new wchar_t[length+1]();
src = const_cast<wchar_t*>(txt.wc_str());
dest = const_cast<wchar_t*>(LabelText);
isActive = ((flags & fc::active) != 0);
isNoUnderline = ((flags & fc::no_underline) != 0);
// find hotkey position in string
// + generate a new string without the '&'-sign
for (uInt i=0; i < length; i++)
{
if ( (i < length) && (txt[i] == '&') && (hotkeypos == -1) )
{
hotkeypos = int(i);
i++;
src++;
}
*dest++ = *src++;
}
if ( hotkeypos != -1 )
length--;
if ( border )
setPrintPos (2, 1);
2015-05-23 13:35:12 +02:00
else
setPrintPos (0, 1);
if ( isEnabled() )
setColor(wc.label_emphasis_fg, wc.label_bg);
else
setColor(wc.label_inactive_fg, wc.label_inactive_bg);
for (int z=0; z < int(length); z++)
{
if ( (z == hotkeypos) && isActive )
{
setColor (wc.label_hotkey_fg, wc.label_hotkey_bg);
if ( ! isNoUnderline )
setUnderline();
print ( LabelText[z] );
if ( ! isNoUnderline )
unsetUnderline();
setColor (wc.label_emphasis_fg, wc.label_bg);
}
else
print ( LabelText[z] );
}
delete[] LabelText;
2015-05-23 13:35:12 +02:00
}
// private methods of FButtonGroup
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
bool FButtonGroup::isRadioButton(FToggleButton* button) const
2015-05-23 13:35:12 +02:00
{
if ( ! button )
return false;
return bool ( std::strcmp ( button->getClassName()
, const_cast<char*>("FRadioButton") ) == 0 );
}
//----------------------------------------------------------------------
void FButtonGroup::init()
{
setTopPadding(1);
setLeftPadding(1);
setBottomPadding(1);
setRightPadding(1);
2015-05-23 13:35:12 +02:00
if ( isEnabled() )
flags |= fc::active;
setForegroundColor (wc.label_fg);
setBackgroundColor (wc.label_bg);
buttonlist.clear(); // no buttons yet
}
//----------------------------------------------------------------------
void FButtonGroup::directFocus()
{
if ( ! hasFocusedButton() )
2015-05-23 13:35:12 +02:00
{
bool found_checked = false;
if ( hasCheckedButton() && ! buttonlist.empty() )
{
FButtonList::const_iterator iter, end;
iter = buttonlist.begin();
end = buttonlist.end();
while ( iter != end )
{
if ( (*iter)->isChecked() )
{
if ( isRadioButton(*iter) )
{
found_checked = true;
FWidget* focused_widget = getFocusWidget();
FFocusEvent out (fc::FocusOut_Event);
FApplication::queueEvent(focused_widget, &out);
(*iter)->setFocus();
if ( focused_widget )
focused_widget->redraw();
focused_widget = getFocusWidget();
if ( focused_widget )
focused_widget->redraw();
}
break;
}
++iter;
}
}
if ( ! found_checked )
{
FWidget* focused_widget = getFocusWidget();
FFocusEvent out (fc::FocusOut_Event);
FApplication::queueEvent(focused_widget, &out);
focusFirstChild();
if ( focused_widget )
focused_widget->redraw();
focused_widget = getFocusWidget();
if ( focused_widget )
focused_widget->redraw();
}
}
if ( getStatusBar() )
{
getStatusBar()->drawMessage();
updateTerminal();
flush_out();
2015-05-23 13:35:12 +02:00
}
}