294 lines
6.1 KiB
C++
294 lines
6.1 KiB
C++
#include "Label.h"
|
|
|
|
#include "Format.h"
|
|
#include "Point.h"
|
|
#include "Keys.h"
|
|
#include "Mouse.h"
|
|
#include "PowderToy.h"
|
|
#include "ContextMenu.h"
|
|
|
|
#include "graphics/Graphics.h"
|
|
|
|
using namespace ui;
|
|
|
|
Label::Label(Point position, Point size, String labelText):
|
|
Component(position, size),
|
|
textColour(255, 255, 255),
|
|
selectionIndexL(textWrapper.IndexBegin()),
|
|
selectionIndexH(textWrapper.IndexBegin()),
|
|
multiline(false),
|
|
selecting(false),
|
|
autoHeight(size.Y==-1?true:false)
|
|
{
|
|
SetText(labelText);
|
|
|
|
menu = new ContextMenu(this);
|
|
menu->AddItem(ContextMenuItem("Copy"_i18n, 0, true));
|
|
}
|
|
|
|
Label::~Label()
|
|
{
|
|
}
|
|
|
|
void Label::SetMultiline(bool status)
|
|
{
|
|
multiline = status;
|
|
updateTextWrapper();
|
|
updateSelection();
|
|
TextPosition(displayTextWrapper.WrappedText());
|
|
}
|
|
|
|
void Label::SetText(String newText)
|
|
{
|
|
this->text = newText;
|
|
updateTextWrapper();
|
|
updateSelection();
|
|
TextPosition(displayTextWrapper.WrappedText());
|
|
}
|
|
|
|
void Label::AutoHeight()
|
|
{
|
|
bool oldAH = autoHeight;
|
|
autoHeight = true;
|
|
updateTextWrapper();
|
|
autoHeight = oldAH;
|
|
}
|
|
|
|
void Label::updateTextWrapper()
|
|
{
|
|
int lines = textWrapper.Update(
|
|
text,
|
|
multiline,
|
|
Size.X - Appearance.Margin.Left - Appearance.Margin.Right
|
|
);
|
|
displayTextWrapper.Update(
|
|
displayText.size() ? displayText : text,
|
|
multiline,
|
|
Size.X - Appearance.Margin.Left - Appearance.Margin.Right
|
|
);
|
|
if (autoHeight)
|
|
{
|
|
Size.Y = lines * FONT_H + 3;
|
|
}
|
|
}
|
|
|
|
String Label::GetText()
|
|
{
|
|
return this->text;
|
|
}
|
|
|
|
void Label::OnContextMenuAction(int item)
|
|
{
|
|
switch(item)
|
|
{
|
|
case 0:
|
|
copySelection();
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Label::OnMouseClick(int x, int y, unsigned button)
|
|
{
|
|
if(button == SDL_BUTTON_RIGHT)
|
|
{
|
|
if (menu)
|
|
{
|
|
menu->Show(GetScreenPos() + ui::Point(x, y));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
selecting = true;
|
|
selectionIndex0 = textWrapper.Point2Index(x - textPosition.X, y - textPosition.Y);
|
|
selectionIndexL = selectionIndex0;
|
|
selectionIndexH = selectionIndex0;
|
|
|
|
updateSelection();
|
|
}
|
|
}
|
|
|
|
void Label::copySelection()
|
|
{
|
|
if (HasSelection())
|
|
{
|
|
ClipboardPush(format::CleanString(text.Between(selectionIndexL.raw_index, selectionIndexH.raw_index), false, true, false).ToUtf8());
|
|
}
|
|
}
|
|
|
|
void Label::OnMouseUp(int x, int y, unsigned button)
|
|
{
|
|
selecting = false;
|
|
}
|
|
|
|
void Label::OnKeyPress(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt)
|
|
{
|
|
if (repeat)
|
|
{
|
|
return;
|
|
}
|
|
if (ctrl && scan == SDL_SCANCODE_C)
|
|
{
|
|
copySelection();
|
|
}
|
|
if (ctrl && scan == SDL_SCANCODE_A)
|
|
{
|
|
selectAll();
|
|
return;
|
|
}
|
|
}
|
|
|
|
void Label::OnMouseMoved(int localx, int localy, int dx, int dy)
|
|
{
|
|
if (selecting)
|
|
{
|
|
selectionIndex1 = textWrapper.Point2Index(localx - textPosition.X, localy - textPosition.Y);
|
|
if (selectionIndex1.raw_index < selectionIndex0.raw_index)
|
|
{
|
|
selectionIndexL = selectionIndex1;
|
|
selectionIndexH = selectionIndex0;
|
|
}
|
|
else
|
|
{
|
|
selectionIndexL = selectionIndex0;
|
|
selectionIndexH = selectionIndex1;
|
|
}
|
|
updateSelection();
|
|
}
|
|
}
|
|
|
|
void Label::Tick(float dt)
|
|
{
|
|
if (!this->IsFocused() && (HasSelection() || selecting))
|
|
{
|
|
ClearSelection();
|
|
}
|
|
}
|
|
|
|
int Label::getLowerSelectionBound()
|
|
{
|
|
return selectionIndexL.raw_index;
|
|
}
|
|
|
|
int Label::getHigherSelectionBound()
|
|
{
|
|
return selectionIndexH.raw_index;
|
|
}
|
|
|
|
bool Label::HasSelection()
|
|
{
|
|
return selectionIndexH.raw_index > selectionIndexL.raw_index;
|
|
}
|
|
|
|
void Label::ClearSelection()
|
|
{
|
|
selecting = false;
|
|
selectionIndexL = textWrapper.IndexBegin();
|
|
selectionIndexH = textWrapper.IndexBegin();
|
|
updateSelection();
|
|
}
|
|
|
|
void Label::selectAll()
|
|
{
|
|
selectionIndexL = textWrapper.IndexBegin();
|
|
selectionIndexH = textWrapper.IndexEnd();
|
|
updateSelection();
|
|
}
|
|
|
|
void Label::updateSelection()
|
|
{
|
|
if (selectionIndexL.raw_index < 0) selectionIndexL = textWrapper.IndexBegin();
|
|
if (selectionIndexL.raw_index > (int)text.length()) selectionIndexL = textWrapper.IndexEnd();
|
|
if (selectionIndexH.raw_index < 0) selectionIndexH = textWrapper.IndexBegin();
|
|
if (selectionIndexH.raw_index > (int)text.length()) selectionIndexH = textWrapper.IndexEnd();
|
|
|
|
displayTextWithSelection = displayTextWrapper.WrappedText();
|
|
if (HasSelection())
|
|
{
|
|
auto indexL = displayTextWrapper.Clear2Index(selectionIndexL.clear_index);
|
|
auto indexH = displayTextWrapper.Clear2Index(selectionIndexH.clear_index);
|
|
displayTextWithSelection.Insert(indexL.wrapped_index , "\x01");
|
|
displayTextWithSelection.Insert(indexH.wrapped_index + 1, "\x01");
|
|
}
|
|
}
|
|
|
|
void Label::SetDisplayText(String newText)
|
|
{
|
|
displayText = newText;
|
|
ClearSelection();
|
|
updateTextWrapper();
|
|
updateSelection();
|
|
TextPosition(displayTextWrapper.WrappedText());
|
|
}
|
|
|
|
void Label::Draw(const Point& screenPos)
|
|
{
|
|
if (!drawn)
|
|
{
|
|
TextPosition(displayTextWrapper.WrappedText());
|
|
updateTextWrapper();
|
|
updateSelection();
|
|
drawn = true;
|
|
}
|
|
Graphics *g = GetGraphics();
|
|
|
|
auto indexL = displayTextWrapper.Clear2Index(selectionIndexL.clear_index);
|
|
auto indexH = displayTextWrapper.Clear2Index(selectionIndexH.clear_index);
|
|
|
|
int selectionXL;
|
|
int selectionYL;
|
|
int selectionLineL = displayTextWrapper.Index2Point(indexL, selectionXL, selectionYL);
|
|
|
|
int selectionXH;
|
|
int selectionYH;
|
|
int selectionLineH = displayTextWrapper.Index2Point(indexH, selectionXH, selectionYH);
|
|
|
|
if (HasSelection())
|
|
{
|
|
if (selectionLineH == selectionLineL)
|
|
{
|
|
g->fillrect(
|
|
screenPos.X + textPosition.X + selectionXL,
|
|
screenPos.Y + textPosition.Y + selectionYL - 1,
|
|
selectionXH - selectionXL,
|
|
FONT_H - 2,
|
|
255, 255, 255, 255
|
|
);
|
|
}
|
|
else
|
|
{
|
|
g->fillrect(
|
|
screenPos.X + textPosition.X + selectionXL,
|
|
screenPos.Y + textPosition.Y + selectionYL - 1,
|
|
textSize.X - selectionXL,
|
|
FONT_H - 2,
|
|
255, 255, 255, 255
|
|
);
|
|
for (int i = 1; i < selectionLineH - selectionLineL; ++i)
|
|
{
|
|
g->fillrect(
|
|
screenPos.X + textPosition.X,
|
|
screenPos.Y + textPosition.Y + selectionYL - 1 + i * FONT_H,
|
|
textSize.X,
|
|
FONT_H - 2,
|
|
255, 255, 255, 255
|
|
);
|
|
}
|
|
g->fillrect(
|
|
screenPos.X + textPosition.X,
|
|
screenPos.Y + textPosition.Y + selectionYH - 1,
|
|
selectionXH,
|
|
FONT_H - 2,
|
|
255, 255, 255, 255
|
|
);
|
|
}
|
|
}
|
|
|
|
g->drawtext(
|
|
screenPos.X + textPosition.X,
|
|
screenPos.Y + textPosition.Y,
|
|
displayTextWithSelection,
|
|
textColour.Red, textColour.Green, textColour.Blue, 255
|
|
);
|
|
}
|
|
|