📄 sgrlistboxcontrol.cpp
字号:
//
// SGRListboxControl.cpp
//
//
#include "SGRListboxControl.hpp"
#define ITEM_MARGIN (4)
#define ITEM_GREEN_COLOR 0xFF, 0xAA, 0xBB, 0x00
#define ITEM_BLUE_COLOR 0xDD, 0xDD, 0xFF, 0x00
#define DEFAULT_INTERVAL 100
#define DEFAULT_FIRSTINTERVAL 500
#define DEFAULT_SPEED 10
SGRListboxControl::SGRListboxControl(SFRResponderPtr responder, SFXRectangleConstRef rect) static_throws : SFRControl(responder, rect, SFXMargin(2, 2, 2, 2), SFMRESPONDERFILTER(LISTBOXCONTROL, BEHAVIOR_LISTBOXCONTROL), ATTRIBUTE_LISTBOXCONTROL)
{
SFXRectangle temp;
if (static_try()) {
static_throw(RegisterHandler(SFEVT_KEY, HANDLER_AFTER, HANDLER_FUNCTION(OnKey)));
if (static_try()) {
static_throw(RegisterHandler(SREVT_RESPONDER_RENDER, SRP16_RENDER_BASE, HANDLER_BEFORE, HANDLER_FUNCTION(OnBase)));
if (static_try()) {
static_throw(RegisterHandler(SREVT_RESPONDER_RENDER, SRP16_RENDER_CONTENT, HANDLER_BEFORE, HANDLER_FUNCTION(OnContent)));
if (static_try()) {
static_throw(RegisterHandler(SFEVT_APP_RESUME, HANDLER_BEFORE, HANDLER_FUNCTION(OnResume)));
if (static_try()) {
static_throw(RegisterHandler(SFEVT_APP_SUSPEND, HANDLER_AFTER, HANDLER_FUNCTION(OnSuspend)));
if (static_try()) {
temp = GetBaseBound();
temp.Deflate(2, 2);
_limit = 0;
_select = 0;
_offset = 0;
_speed = DEFAULT_SPEED;
_height = SFXGraphics::GetFontHeight(AEE_FONT_NORMAL) + ITEM_MARGIN;
_field = temp.GetHeight() / _height;
_delta = 0;
_interval = DEFAULT_INTERVAL;
_firstinterval = DEFAULT_FIRSTINTERVAL;
_drawWidth = temp.GetWidth();
temp.SetHeight(_field * _height);
temp.Deflate(-2, -2);
temp.Offset(SFXGrid((GetBaseBound().GetSize() - temp.GetSize()) / 2));
SetBaseBound(temp);
}
}
}
}
}
}
return;
}
SGRListboxControl::~SGRListboxControl(Void)
{
StopTimer();
Clear();
return;
}
SInt16 SGRListboxControl::GetItemCount(Void) const
{
return _limit;
}
Void SGRListboxControl::SetSelect(SInt16 value)
{
if (value >= _limit) {
value = _limit - 1;
}
if (value < 0) {
value = 0;
}
_select = value;
RestartTimer();
RefreshDelta();
InvalidateContent();
return;
}
SInt16 SGRListboxControl::GetSelect(Void) const
{
return _select;
}
Void SGRListboxControl::SetDelta(SInt16 value)
{
if (value > _limit - _field) {
value = _limit - _field;
}
if (value < 0) {
value = 0;
}
_delta = value;
RefreshDelta();
InvalidateContent();
return;
}
SInt16 SGRListboxControl::GetDelta(Void) const
{
return _delta;
}
Void SGRListboxControl::SetInterval(SInt16 interval)
{
_interval = interval;
}
SInt16 SGRListboxControl::GetInterval(Void) const
{
return _interval;
}
Void SGRListboxControl::SetFirstInterval(SInt16 interval)
{
_firstinterval = interval;
}
SInt16 SGRListboxControl::GetFirstInterval(Void) const
{
return _firstinterval;
}
Void SGRListboxControl::SetSpeed(SInt16 speed)
{
_speed = speed;
}
SInt16 SGRListboxControl::GetSpeed(Void) const
{
return _speed;
}
SFCError SGRListboxControl::Append(SFXAnsiStringConstRef item)
{
SFXAnsiStringPtr string;
SFCError error(SFERR_NO_ERROR);
if ((string = ::new SFXAnsiString(item)) != null) {
if (_item.Append(string) == SFERR_NO_ERROR) {
++_limit;
// 弶夞偼僞僀儅乕婲摦
if (_item.GetSize() == 1) {
StartTimer();
}
RefreshDelta();
InvalidateContent();
}
else {
::delete string;
error = SFERR_FAILED;
}
}
else {
error = SFERR_NO_MEMORY;
}
return error;
}
Void SGRListboxControl::Remove(SInt16 index)
{
if (!_item.IsEmpty()) {
if (index < 0) {
index = 0;
}
else if (index >= _item.GetSize()) {
index = static_cast<SInt16>(_item.GetSize()) - 1;
}
delete _item[index];
_item.Remove(index);
if (_item.GetSize() <= 0) {
StopTimer();
}
--_limit;
if (index < _select) {
--_select;
RefreshDelta();
RestartTimer();
}
else if (_select >= _item.GetSize()) {
if (_select > 0) {
--_select;
}
if (_delta > 0) {
--_delta;
}
RefreshDelta();
RestartTimer();
}
InvalidateContent();
}
}
Void SGRListboxControl::Clear(Void)
{
SFXArray<SFXAnsiStringPtr>::Enumerator it(_item.GetEnumerator());
if (it.IsValid()) {
while (it.HasNext()) {
::delete it.GetNext();
}
}
_item.Clear();
_limit = 0;
_select = 0;
StopTimer();
RefreshDelta();
InvalidateContent();
return;
}
HANDLER_IMPLEMENT_BOOLEVENT(SGRListboxControl, OnKey, event)
{
Bool result(true);
switch (event.GetP16()) {
case AVK_SELECT:
if (_limit > 0) {
Invoke(SFXEvent(SREVT_CONTROL, _select, reinterpret_cast<UInt32>(this)));
}
break;
case AVK_CLR:
SetStatusTarget(false);
Invoke(SFXEvent(SREVT_CONTROL, SRP16_ESCAPE, reinterpret_cast<UInt32>(this)));
break;
case AVK_UP:
if (_select > 0) {
--_select;
RestartTimer();
RefreshDelta();
InvalidateContent();
}
break;
case AVK_DOWN:
if (_select < _limit - 1) {
++_select;
RestartTimer();
RefreshDelta();
InvalidateContent();
}
break;
default:
result = false;
break;
}
return result;
}
HANDLER_IMPLEMENT_VOIDRENDER(SGRListboxControl, OnBase, graphics)
{
SFXRectangle rect(GetBaseWorld());
SFXBevelColor frameRgb(SFXRGBColor(0xAA, 0xAA, 0xAA, 0x00), SFXRGBColor(0xFF, 0xFF, 0xFF, 0x00), SFXRGBColor(0xFF, 0xFF, 0xFF, 0x00));
if (GetInheritEnable()) {
graphics->DrawBevelRectangle(rect, frameRgb);
rect.Deflate(1, 1);
graphics->DrawRectangle(rect, SFXRGBColor(0x00, 0x00, 0x00, 0x00));
}
else {
graphics->FillRectangle(rect, frameRgb.GetBase());
rect.Deflate(1, 1);
graphics->DrawRectangle(rect, SFXRGBColor(0x66, 0x66, 0x66, 0x00));
}
return;
}
HANDLER_IMPLEMENT_VOIDRENDER(SGRListboxControl, OnContent, graphics)
{
SFXRectangle rect(GetContentWorld());
SFXRectangle temp;
SFXRGBColor blue(ITEM_BLUE_COLOR);
SInt16 r0;
Bool next;
Bool previous;
if (!GetInheritEnable()) {
blue.AddRGB(0x11);
}
next = (_delta + _field < _limit);
previous = (_delta > 0);
rect.SetHeight(_height);
for (r0 = 0; r0 < _field; ++r0) {
graphics->FillRectangle(rect, ((r0 + _delta) % 2 == 0) ? SFXRGBColor(0xFF, 0xFF, 0xFF, 0x00) : blue);
if (r0 + _delta < _limit) {
temp = rect;
if (r0 + _delta == _select) {
if (GetInheritEnable() && GetInheritFocus() && GetInheritTarget()) {
graphics->FillRectangle(temp, SFXRGBColor(ITEM_GREEN_COLOR));
}
}
DrawItem(graphics, temp, r0 + _delta, next && (r0 == _field - 1), previous && (r0 == 0), r0 + _delta == _select ? _offset : 0);
}
rect.Offset(0, rect.GetHeight());
}
return;
}
HANDLER_IMPLEMENT_VOIDRESUME(SGRListboxControl, OnResume, environment)
{
unused(environment);
StartTimer();
return;
}
HANDLER_IMPLEMENT_VOIDSUSPEND(SGRListboxControl, OnSuspend, reason, info)
{
unused(reason);
unused(info);
StopTimer();
return;
}
Void SGRListboxControl::RefreshDelta(Void)
{
if (_select < _delta) {
_delta = _select;
}
else if (_select >= _delta + _field) {
_delta = _select - _field + 1;
}
return;
}
Void SGRListboxControl::DrawItem(SFXGraphicsPtr graphics, SFXRectangleConstRef rect, SInt16 index, Bool next, Bool previous, SInt16 offset)
{
SFXRectangle text(rect);
SFXGrid grid;
SFXRectangle icon;
SInt16 temp;
text.Deflate(4, 1);
if (next || previous) {
icon = text;
icon.Deflate(icon.GetWidth() - icon.GetHeight(), 0, -1, 0);
temp = 0;
if (previous) {
temp = DrawTriangle(graphics, icon, false, SFXRGBColor(0x00, 0x00, 0x00, 0x00));
}
if (next) {
temp = DrawTriangle(graphics, icon, true, SFXRGBColor(0x00, 0x00, 0x00, 0x00));
}
text.Deflate(0, 0, temp, 0);
}
grid = text.GetOrigin();
grid.SubX(offset);
graphics->DrawText(*_item.Get(index), grid, text, SFXRGBColor(0x00, 0x00, 0x00, 0x00), IDF_ALIGN_LEFT);
return;
}
SInt16 SGRListboxControl::DrawTriangle(SFXGraphicsPtr graphics, SFXRectangleConstRef rect, Bool figure, SFXRGBColorConstRef color)
{
SFXTriangle triangle;
SFXPixel point;
SFXSize size;
size.SetHeight(rect.GetHeight() / 4);
size.SetWidth(size.GetHeight() * 2 - 1);
point.Set(rect.GetX() + rect.GetWidth() - size.GetHeight() - size.GetWidth() + 1, rect.GetY() + ((figure) ? (rect.GetHeight() - size.GetWidth()) : (size.GetWidth() - 1)));
triangle.SetFirst(point);
point.Offset((size.GetWidth() - 1) / 2, (figure) ? (size.GetHeight() - 1) : (1 - size.GetHeight()));
triangle.SetSecond(point);
point.Offset((size.GetWidth() - 1) / 2, (figure) ? (1 - size.GetHeight()) : (size.GetHeight() - 1));
triangle.SetThird(point);
graphics->SetForeColor(color);
graphics->SetFillColor(color);
graphics->SetFillMode(true);
graphics->DrawTriangle(triangle);
return size.GetWidth() + (size.GetHeight() - 1) * 2;
}
Void SGRListboxControl::OnTimer(Void)
{
SInt16 textWidth;
textWidth = SFXGraphics::MeasureText(AEE_FONT_NORMAL, *_item.Get(_select));
if (textWidth > _drawWidth) {
_offset += _speed;
}
if (_offset > textWidth) {
_offset = -_drawWidth;
}
InvalidateContent();
SFRApplication::GetInstance()->Invoke(SFXEvent(SREVT_RESPONDER_RENDER, SRP16_RENDER_INVOKE, false));
SFBShell::GetInstance()->SetTimer(_interval, OnTimerEntry, this);
}
Void SGRListboxControl::OnTimerEntry(VoidPtr reference)
{
static_cast<SGRListboxControlPtr>(reference)->OnTimer();
}
Void SGRListboxControl::StartTimer(Void)
{
SFBShell::GetInstance()->SetTimer(_firstinterval, OnTimerEntry, this);
}
Void SGRListboxControl::StopTimer(Void)
{
_offset = 0;
SFBShell::GetInstance()->CancelTimer(OnTimerEntry, this);
}
Void SGRListboxControl::RestartTimer(Void)
{
SFBShell::GetInstance()->CancelTimer(OnTimerEntry, this);
_offset = 0;
SFBShell::GetInstance()->SetTimer(_firstinterval, OnTimerEntry, this);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -