mirror of https://github.com/PCSX2/pcsx2.git
392 lines
9.2 KiB
C++
392 lines
9.2 KiB
C++
/* PCSX2 - PS2 Emulator for PCs
|
|
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
|
*
|
|
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
|
* of the GNU Lesser General Public License as published by the Free Software Found-
|
|
* ation, either version 3 of the License, or (at your option) any later version.
|
|
*
|
|
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with PCSX2.
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <wx/wizard.h>
|
|
#include "common/pxStaticText.h"
|
|
#include "common/Assertions.h"
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// pxStaticText (implementations)
|
|
// --------------------------------------------------------------------------------------
|
|
pxStaticText::pxStaticText(wxWindow* parent)
|
|
: _parent(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNO_BORDER)
|
|
{
|
|
m_align = wxALIGN_CENTRE_HORIZONTAL;
|
|
m_autowrap = true;
|
|
m_wrappedWidth = -1;
|
|
m_heightInLines = 1;
|
|
|
|
SetPaddingDefaults();
|
|
}
|
|
|
|
pxStaticText::pxStaticText(wxWindow* parent, const wxString& label, wxAlignment align)
|
|
: _parent(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNO_BORDER)
|
|
{
|
|
m_heightInLines = 1;
|
|
m_align = align;
|
|
|
|
SetPaddingDefaults();
|
|
Init(label);
|
|
}
|
|
|
|
void pxStaticText::Init(const wxString& label)
|
|
{
|
|
m_autowrap = true;
|
|
m_wrappedWidth = -1;
|
|
m_label = label;
|
|
Bind(wxEVT_PAINT, &pxStaticText::paintEvent, this);
|
|
}
|
|
|
|
// we need to refresh the window after changing its size as the standard
|
|
// control doesn't always update itself properly (fials typically on window resizes where
|
|
// the control is expanded to fit -- ie the control's size changes but the position does not)
|
|
void pxStaticText::DoSetSize(int x, int y, int w, int h, int sizeFlags)
|
|
{
|
|
_parent::DoSetSize(x, y, w, h, sizeFlags);
|
|
Refresh();
|
|
}
|
|
|
|
void pxStaticText::SetPaddingDefaults()
|
|
{
|
|
m_paddingPix_horiz = 7;
|
|
m_paddingPix_vert = 1;
|
|
|
|
m_paddingPct_horiz = 0.0f;
|
|
m_paddingPct_vert = 0.0f;
|
|
}
|
|
|
|
pxStaticText& pxStaticText::SetMinWidth(int width)
|
|
{
|
|
SetMinSize(wxSize(width, GetMinHeight()));
|
|
return *this;
|
|
}
|
|
|
|
pxStaticText& pxStaticText::SetMinHeight(int height)
|
|
{
|
|
SetMinSize(wxSize(GetMinWidth(), height));
|
|
return *this;
|
|
}
|
|
|
|
pxStaticText& pxStaticText::SetHeight(int lines)
|
|
{
|
|
if (!pxAssert(lines > 0))
|
|
lines = 2;
|
|
m_heightInLines = lines;
|
|
|
|
const int newHeight = (pxGetCharHeight(this) * m_heightInLines) + (m_paddingPix_vert * 2);
|
|
SetMinSize(wxSize(GetMinWidth(), newHeight));
|
|
|
|
return *this;
|
|
}
|
|
|
|
pxStaticText& pxStaticText::Align(wxAlignment align)
|
|
{
|
|
m_align = align;
|
|
return *this;
|
|
}
|
|
|
|
pxStaticText& pxStaticText::Bold()
|
|
{
|
|
wxFont bold(GetFont());
|
|
bold.SetWeight(wxFONTWEIGHT_BOLD);
|
|
SetFont(bold);
|
|
return *this;
|
|
}
|
|
|
|
pxStaticText& pxStaticText::PaddingPixH(int pixels)
|
|
{
|
|
m_paddingPix_horiz = pixels;
|
|
UpdateWrapping(false);
|
|
Refresh();
|
|
return *this;
|
|
}
|
|
|
|
pxStaticText& pxStaticText::PaddingPixV(int pixels)
|
|
{
|
|
m_paddingPix_vert = pixels;
|
|
Refresh();
|
|
return *this;
|
|
}
|
|
|
|
pxStaticText& pxStaticText::PaddingPctH(float pct)
|
|
{
|
|
pxAssert(pct < 0.5);
|
|
|
|
m_paddingPct_horiz = pct;
|
|
UpdateWrapping(false);
|
|
Refresh();
|
|
return *this;
|
|
}
|
|
|
|
pxStaticText& pxStaticText::PaddingPctV(float pct)
|
|
{
|
|
pxAssert(pct < 0.5);
|
|
|
|
m_paddingPct_vert = pct;
|
|
Refresh();
|
|
return *this;
|
|
}
|
|
|
|
pxStaticText& pxStaticText::Unwrapped()
|
|
{
|
|
m_autowrap = false;
|
|
UpdateWrapping(false);
|
|
return *this;
|
|
}
|
|
|
|
int pxStaticText::calcPaddingWidth(int newWidth) const
|
|
{
|
|
return (int)(newWidth * m_paddingPct_horiz * 2) + (m_paddingPix_horiz * 2);
|
|
}
|
|
|
|
int pxStaticText::calcPaddingHeight(int newHeight) const
|
|
{
|
|
return (int)(newHeight * m_paddingPct_vert * 2) + (m_paddingPix_vert * 2);
|
|
}
|
|
|
|
wxSize pxStaticText::GetBestWrappedSize(const wxClientDC& dc) const
|
|
{
|
|
pxAssert(m_autowrap);
|
|
|
|
// Find an ideal(-ish) width, based on a search of all parent controls and their
|
|
// valid Minimum sizes.
|
|
|
|
int idealWidth = wxDefaultCoord;
|
|
int parentalAdjust = 0;
|
|
double parentalFactor = 1.0;
|
|
const wxWindow* millrun = this;
|
|
|
|
while (millrun)
|
|
{
|
|
// IMPORTANT : wxWizard changes its min size and then expects everything else
|
|
// to play nice and NOT resize according to the new min size. (wtf stupid)
|
|
// Anyway, this fixes it -- ignore min size specifier on wxWizard!
|
|
if (wxIsKindOf(millrun, wxWizard))
|
|
break;
|
|
|
|
int min = (int)((millrun->GetMinWidth() - parentalAdjust) * parentalFactor);
|
|
|
|
if (min > 0 && ((idealWidth < 0) || (min < idealWidth)))
|
|
{
|
|
idealWidth = min;
|
|
}
|
|
|
|
parentalAdjust += pxSizerFlags::StdPadding * 2;
|
|
millrun = millrun->GetParent();
|
|
}
|
|
|
|
if (idealWidth <= 0)
|
|
{
|
|
// FIXME: The minimum size of this control is unknown, so let's just pick a guess based on
|
|
// the size of the user's display area.
|
|
|
|
idealWidth = (int)(wxGetDisplaySize().GetWidth() * 0.66) - (parentalAdjust * 2);
|
|
}
|
|
|
|
return dc.GetMultiLineTextExtent(pxTextWrapper().Wrap(this, m_label, idealWidth - calcPaddingWidth(idealWidth)).GetResult());
|
|
}
|
|
|
|
pxStaticText& pxStaticText::WrapAt(int width)
|
|
{
|
|
m_autowrap = false;
|
|
|
|
if ((width <= 1) || (width == m_wrappedWidth))
|
|
return *this;
|
|
|
|
wxString wrappedLabel;
|
|
m_wrappedWidth = width;
|
|
|
|
if (width > 1)
|
|
wrappedLabel = pxTextWrapper().Wrap(this, m_label, width).GetResult();
|
|
|
|
if (m_wrappedLabel != wrappedLabel)
|
|
{
|
|
m_wrappedLabel = wrappedLabel;
|
|
wxSize area = wxClientDC(this).GetMultiLineTextExtent(m_wrappedLabel);
|
|
SetMinSize(wxSize(
|
|
area.GetWidth() + calcPaddingWidth(area.GetWidth()),
|
|
area.GetHeight() + calcPaddingHeight(area.GetHeight())));
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
bool pxStaticText::_updateWrapping(bool textChanged)
|
|
{
|
|
if (!m_autowrap)
|
|
{
|
|
//m_wrappedLabel = wxEmptyString;
|
|
//m_wrappedWidth = -1;
|
|
return false;
|
|
}
|
|
|
|
wxString wrappedLabel;
|
|
int newWidth = GetSize().GetWidth();
|
|
|
|
if (!textChanged && (newWidth == m_wrappedWidth))
|
|
return false;
|
|
|
|
// Note: during various stages of sizer-calc, width can be 1, 0, or -1.
|
|
// We ignore wrapping in these cases. (the PaintEvent also checks the wrapping
|
|
// and updates it if needed, in case the control's size isn't figured out prior
|
|
// to being painted).
|
|
|
|
m_wrappedWidth = newWidth;
|
|
if (m_wrappedWidth > 1)
|
|
wrappedLabel = pxTextWrapper().Wrap(this, m_label, m_wrappedWidth).GetResult();
|
|
|
|
if (m_wrappedLabel == wrappedLabel)
|
|
return false;
|
|
m_wrappedLabel = wrappedLabel;
|
|
|
|
return true;
|
|
}
|
|
|
|
void pxStaticText::UpdateWrapping(bool textChanged)
|
|
{
|
|
if (_updateWrapping(textChanged))
|
|
Refresh();
|
|
}
|
|
|
|
void pxStaticText::SetLabel(const wxString& label)
|
|
{
|
|
const bool labelChanged(label != m_label);
|
|
if (labelChanged)
|
|
{
|
|
m_label = label;
|
|
Refresh();
|
|
}
|
|
|
|
// Always update wrapping, in case window width or something else also changed.
|
|
UpdateWrapping(labelChanged);
|
|
InvalidateBestSize();
|
|
}
|
|
|
|
wxFont pxStaticText::GetFontOk() const
|
|
{
|
|
wxFont font(GetFont());
|
|
if (!font.Ok())
|
|
return wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
|
|
return font;
|
|
}
|
|
|
|
bool pxStaticText::Enable(bool enabled)
|
|
{
|
|
if (_parent::Enable(enabled))
|
|
{
|
|
Refresh();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void pxStaticText::paintEvent(wxPaintEvent& evt)
|
|
{
|
|
wxPaintDC dc(this);
|
|
const int dcWidth = dc.GetSize().GetWidth();
|
|
const int dcHeight = dc.GetSize().GetHeight();
|
|
if (dcWidth < 1)
|
|
return;
|
|
dc.SetFont(GetFontOk());
|
|
|
|
if (IsEnabled())
|
|
dc.SetTextForeground(GetForegroundColour());
|
|
else
|
|
dc.SetTextForeground(*wxLIGHT_GREY);
|
|
|
|
pxWindowTextWriter writer(dc);
|
|
writer.Align(m_align);
|
|
|
|
const wxString& label(m_autowrap ? m_wrappedLabel : m_label);
|
|
if (m_autowrap)
|
|
_updateWrapping(false);
|
|
|
|
int tWidth, tHeight;
|
|
dc.GetMultiLineTextExtent(label, &tWidth, &tHeight);
|
|
|
|
writer.Align(m_align);
|
|
if (m_align & wxALIGN_CENTER_VERTICAL)
|
|
writer.SetY((dcHeight - tHeight) / 2);
|
|
else
|
|
writer.SetY((int)(dcHeight * m_paddingPct_vert) + m_paddingPix_vert);
|
|
|
|
writer.WriteLn(label); // without formatting please.
|
|
|
|
//dc.SetBrush( *wxTRANSPARENT_BRUSH );
|
|
//dc.DrawRectangle(wxPoint(), dc.GetSize());
|
|
}
|
|
|
|
// Overloaded form wxPanel and friends.
|
|
wxSize pxStaticText::DoGetBestSize() const
|
|
{
|
|
wxClientDC dc(const_cast<pxStaticText*>(this));
|
|
dc.SetFont(GetFontOk());
|
|
|
|
wxSize best;
|
|
|
|
if (m_autowrap)
|
|
{
|
|
best = GetBestWrappedSize(dc);
|
|
//best.x = wxDefaultCoord;
|
|
}
|
|
else
|
|
{
|
|
// No autowrapping, so we can force a specific size here!
|
|
best = dc.GetMultiLineTextExtent(GetLabel());
|
|
best.x += calcPaddingWidth(best.x);
|
|
}
|
|
|
|
best.y += calcPaddingHeight(best.y);
|
|
|
|
CacheBestSize(best);
|
|
return best;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// pxStaticHeading (implementations)
|
|
// --------------------------------------------------------------------------------------
|
|
pxStaticHeading::pxStaticHeading(wxWindow* parent, const wxString& label)
|
|
: _parent(parent)
|
|
{
|
|
m_align = wxALIGN_CENTER;
|
|
|
|
SetPaddingDefaults();
|
|
Init(label);
|
|
}
|
|
|
|
void pxStaticHeading::SetPaddingDefaults()
|
|
{
|
|
m_paddingPix_horiz = 4;
|
|
m_paddingPix_vert = 1;
|
|
|
|
m_paddingPct_horiz = 0.08f;
|
|
m_paddingPct_vert = 0.0f;
|
|
}
|
|
|
|
void operator+=(wxSizer& target, pxStaticText* src)
|
|
{
|
|
if (src)
|
|
target.Add(src, pxExpand);
|
|
}
|
|
|
|
void operator+=(wxSizer& target, pxStaticText& src)
|
|
{
|
|
target.Add(&src, pxExpand);
|
|
}
|
|
|
|
void operator+=(wxSizer* target, pxStaticText& src)
|
|
{
|
|
target->Add(&src, pxExpand);
|
|
}
|