mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-20 19:22:47 +01:00
297 lines
8.7 KiB
C++
297 lines
8.7 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/generic/hyperlinkg.cpp
|
|
// Purpose: Hyperlink control
|
|
// Author: David Norris <danorris@gmail.com>, Otto Wyss
|
|
// Modified by: Ryan Norton, Francesco Montorsi
|
|
// Created: 04/02/2005
|
|
// Copyright: (c) 2005 David Norris
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ============================================================================
|
|
// declarations
|
|
// ============================================================================
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Pre-compiled header stuff
|
|
//---------------------------------------------------------------------------
|
|
|
|
// For compilers that support precompilation, includes "wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#ifdef __BORLANDC__
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#if wxUSE_HYPERLINKCTRL
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Includes
|
|
//---------------------------------------------------------------------------
|
|
|
|
#include "wx/hyperlink.h"
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/utils.h" // for wxLaunchDefaultBrowser
|
|
#include "wx/dcclient.h"
|
|
#include "wx/menu.h"
|
|
#include "wx/log.h"
|
|
#include "wx/dataobj.h"
|
|
#endif
|
|
|
|
#include "wx/clipbrd.h"
|
|
#include "wx/renderer.h"
|
|
|
|
// ============================================================================
|
|
// implementation
|
|
// ============================================================================
|
|
|
|
// reserved for internal use only
|
|
#define wxHYPERLINK_POPUP_COPY_ID 16384
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxGenericHyperlinkCtrl
|
|
// ----------------------------------------------------------------------------
|
|
|
|
bool wxGenericHyperlinkCtrl::Create(wxWindow *parent, wxWindowID id,
|
|
const wxString& label, const wxString& url, const wxPoint& pos,
|
|
const wxSize& size, long style, const wxString& name)
|
|
{
|
|
// do validation checks:
|
|
CheckParams(label, url, style);
|
|
|
|
if ((style & wxHL_ALIGN_LEFT) == 0)
|
|
style |= wxFULL_REPAINT_ON_RESIZE;
|
|
|
|
if (!wxControl::Create(parent, id, pos, size, style, wxDefaultValidator, name))
|
|
return false;
|
|
|
|
// set to non empty strings both the url and the label
|
|
SetURL(url.empty() ? label : url);
|
|
SetLabel(label.empty() ? url : label);
|
|
|
|
Init();
|
|
SetForegroundColour(m_normalColour);
|
|
|
|
// by default the font of an hyperlink control is underlined
|
|
wxFont f = GetFont();
|
|
f.SetUnderlined(true);
|
|
SetFont(f);
|
|
|
|
SetInitialSize(size);
|
|
|
|
|
|
// connect our event handlers:
|
|
// NOTE: since this class is the base class of the GTK+'s native implementation
|
|
// of wxHyperlinkCtrl, we cannot use the static macros in BEGIN/END_EVENT_TABLE
|
|
// blocks, otherwise the GTK+'s native impl of wxHyperlinkCtrl would not
|
|
// behave correctly (as we intercept events doing things which interfere
|
|
// with GTK+'s native handling):
|
|
|
|
Connect( wxEVT_PAINT, wxPaintEventHandler(wxGenericHyperlinkCtrl::OnPaint) );
|
|
Connect( wxEVT_SET_FOCUS, wxFocusEventHandler(wxGenericHyperlinkCtrl::OnFocus) );
|
|
Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler(wxGenericHyperlinkCtrl::OnFocus) );
|
|
Connect( wxEVT_CHAR, wxKeyEventHandler(wxGenericHyperlinkCtrl::OnChar) );
|
|
Connect( wxEVT_LEAVE_WINDOW, wxMouseEventHandler(wxGenericHyperlinkCtrl::OnLeaveWindow) );
|
|
|
|
Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler(wxGenericHyperlinkCtrl::OnLeftDown) );
|
|
Connect( wxEVT_LEFT_UP, wxMouseEventHandler(wxGenericHyperlinkCtrl::OnLeftUp) );
|
|
Connect( wxEVT_MOTION, wxMouseEventHandler(wxGenericHyperlinkCtrl::OnMotion) );
|
|
|
|
ConnectMenuHandlers();
|
|
|
|
return true;
|
|
}
|
|
|
|
void wxGenericHyperlinkCtrl::Init()
|
|
{
|
|
m_rollover = false;
|
|
m_clicking = false;
|
|
m_visited = false;
|
|
|
|
// colours
|
|
m_normalColour = *wxBLUE;
|
|
m_hoverColour = *wxRED;
|
|
m_visitedColour = wxColour("#551a8b");
|
|
}
|
|
|
|
void wxGenericHyperlinkCtrl::ConnectMenuHandlers()
|
|
{
|
|
// Connect the event handlers for the context menu.
|
|
Connect( wxEVT_RIGHT_UP, wxMouseEventHandler(wxGenericHyperlinkCtrl::OnRightUp) );
|
|
Connect( wxHYPERLINK_POPUP_COPY_ID, wxEVT_MENU,
|
|
wxCommandEventHandler(wxGenericHyperlinkCtrl::OnPopUpCopy) );
|
|
}
|
|
|
|
wxSize wxGenericHyperlinkCtrl::DoGetBestClientSize() const
|
|
{
|
|
wxClientDC dc((wxWindow *)this);
|
|
return dc.GetTextExtent(GetLabel());
|
|
}
|
|
|
|
|
|
void wxGenericHyperlinkCtrl::SetNormalColour(const wxColour &colour)
|
|
{
|
|
m_normalColour = colour;
|
|
if (!m_visited)
|
|
{
|
|
SetForegroundColour(m_normalColour);
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
void wxGenericHyperlinkCtrl::SetVisitedColour(const wxColour &colour)
|
|
{
|
|
m_visitedColour = colour;
|
|
if (m_visited)
|
|
{
|
|
SetForegroundColour(m_visitedColour);
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
void wxGenericHyperlinkCtrl::DoContextMenu(const wxPoint &pos)
|
|
{
|
|
wxMenu *menuPopUp = new wxMenu(wxEmptyString, wxMENU_TEAROFF);
|
|
menuPopUp->Append(wxHYPERLINK_POPUP_COPY_ID, _("&Copy URL"));
|
|
PopupMenu( menuPopUp, pos );
|
|
delete menuPopUp;
|
|
}
|
|
|
|
wxRect wxGenericHyperlinkCtrl::GetLabelRect() const
|
|
{
|
|
// our best size is always the size of the label without borders
|
|
wxSize c(GetClientSize()), b(GetBestSize());
|
|
wxPoint offset;
|
|
|
|
// the label is always centered vertically
|
|
offset.y = (c.GetHeight()-b.GetHeight())/2;
|
|
|
|
if (HasFlag(wxHL_ALIGN_CENTRE))
|
|
offset.x = (c.GetWidth()-b.GetWidth())/2;
|
|
else if (HasFlag(wxHL_ALIGN_RIGHT))
|
|
offset.x = c.GetWidth()-b.GetWidth();
|
|
else if (HasFlag(wxHL_ALIGN_LEFT))
|
|
offset.x = 0;
|
|
return wxRect(offset, b);
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxGenericHyperlinkCtrl - event handlers
|
|
// ----------------------------------------------------------------------------
|
|
|
|
void wxGenericHyperlinkCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
|
|
{
|
|
wxPaintDC dc(this);
|
|
dc.SetFont(GetFont());
|
|
dc.SetTextForeground(GetForegroundColour());
|
|
dc.SetTextBackground(GetBackgroundColour());
|
|
|
|
dc.DrawText(GetLabel(), GetLabelRect().GetTopLeft());
|
|
if (HasFocus())
|
|
{
|
|
wxRendererNative::Get().DrawFocusRect(this, dc, GetClientRect(), wxCONTROL_SELECTED);
|
|
}
|
|
}
|
|
|
|
void wxGenericHyperlinkCtrl::OnFocus(wxFocusEvent& event)
|
|
{
|
|
Refresh();
|
|
event.Skip();
|
|
}
|
|
|
|
void wxGenericHyperlinkCtrl::OnChar(wxKeyEvent& event)
|
|
{
|
|
switch (event.m_keyCode)
|
|
{
|
|
default:
|
|
event.Skip();
|
|
break;
|
|
case WXK_SPACE:
|
|
case WXK_NUMPAD_SPACE:
|
|
SetForegroundColour(m_visitedColour);
|
|
m_visited = true;
|
|
SendEvent();
|
|
break;
|
|
}
|
|
}
|
|
|
|
void wxGenericHyperlinkCtrl::OnLeftDown(wxMouseEvent& event)
|
|
{
|
|
// the left click must start from the hyperlink rect
|
|
m_clicking = GetLabelRect().Contains(event.GetPosition());
|
|
}
|
|
|
|
void wxGenericHyperlinkCtrl::OnLeftUp(wxMouseEvent& event)
|
|
{
|
|
// the click must be started and ended in the hyperlink rect
|
|
if (!m_clicking || !GetLabelRect().Contains(event.GetPosition()))
|
|
return;
|
|
|
|
SetForegroundColour(m_visitedColour);
|
|
m_visited = true;
|
|
m_clicking = false;
|
|
|
|
// send the event
|
|
SendEvent();
|
|
}
|
|
|
|
void wxGenericHyperlinkCtrl::OnRightUp(wxMouseEvent& event)
|
|
{
|
|
if( GetWindowStyle() & wxHL_CONTEXTMENU )
|
|
if ( GetLabelRect().Contains(event.GetPosition()) )
|
|
DoContextMenu(wxPoint(event.m_x, event.m_y));
|
|
}
|
|
|
|
void wxGenericHyperlinkCtrl::OnMotion(wxMouseEvent& event)
|
|
{
|
|
wxRect textrc = GetLabelRect();
|
|
|
|
if (textrc.Contains(event.GetPosition()))
|
|
{
|
|
SetCursor(wxCursor(wxCURSOR_HAND));
|
|
SetForegroundColour(m_hoverColour);
|
|
m_rollover = true;
|
|
Refresh();
|
|
}
|
|
else if (m_rollover)
|
|
{
|
|
SetCursor(*wxSTANDARD_CURSOR);
|
|
SetForegroundColour(!m_visited ? m_normalColour : m_visitedColour);
|
|
m_rollover = false;
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
void wxGenericHyperlinkCtrl::OnLeaveWindow(wxMouseEvent& WXUNUSED(event) )
|
|
{
|
|
// NB: when the label rect and the client size rect have the same
|
|
// height this function is indispensable to remove the "rollover"
|
|
// effect as the OnMotion() event handler could not be called
|
|
// in that case moving the mouse out of the label vertically...
|
|
|
|
if (m_rollover)
|
|
{
|
|
SetCursor(*wxSTANDARD_CURSOR);
|
|
SetForegroundColour(!m_visited ? m_normalColour : m_visitedColour);
|
|
m_rollover = false;
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
void wxGenericHyperlinkCtrl::OnPopUpCopy( wxCommandEvent& WXUNUSED(event) )
|
|
{
|
|
#if wxUSE_CLIPBOARD
|
|
if (!wxTheClipboard->Open())
|
|
return;
|
|
|
|
wxTextDataObject *data = new wxTextDataObject( m_url );
|
|
wxTheClipboard->SetData( data );
|
|
wxTheClipboard->Close();
|
|
#endif // wxUSE_CLIPBOARD
|
|
}
|
|
|
|
#endif // wxUSE_HYPERLINKCTRL
|