Aegisub/contrib/assdraw/src/dlgctrl.cpp

376 lines
14 KiB
C++

/*
* Copyright (c) 2007, ai-chan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the ASSDraw3 Team nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AI-CHAN ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL AI-CHAN BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
///////////////////////////////////////////////////////////////////////////////
// Name: dlgctrl.cpp
// Purpose: custom dialogs and controls
// Author: ai-chan
// Created: 08/26/06
// Copyright: (c) ai-chan
// Licence: 3-clause BSD
///////////////////////////////////////////////////////////////////////////////
#include "assdraw.hpp"
#if !defined(__WINDOWS__)
#include "xpm/res.h"
#endif
BEGIN_EVENT_TABLE(ASSDrawSrcTxtCtrl, wxTextCtrl)
EVT_CHAR(ASSDrawSrcTxtCtrl::CustomOnChar)
EVT_TEXT(wxID_ANY, ASSDrawSrcTxtCtrl::CustomOnText)
END_EVENT_TABLE()
BEGIN_EVENT_TABLE(ASSDrawTransformDlg, wxDialog)
EVT_COMBOBOX(-1, ASSDrawTransformDlg::OnTemplatesCombo)
END_EVENT_TABLE()
//BEGIN_EVENT_TABLE(ASSDrawCanvasRecenterButton, wxWindow)
//END_EVENT_TABLE()
// ----------------------------------------------------------------------------
// ASSDrawSrcTxtCtrl
// ----------------------------------------------------------------------------
ASSDrawSrcTxtCtrl::ASSDrawSrcTxtCtrl(wxWindow *parent, ASSDrawFrame *frame)
: wxTextCtrl(parent, wxID_ANY, _T(""), __DPDS__ , wxTE_MULTILINE )
{
m_frame = frame;
}
void ASSDrawSrcTxtCtrl::CustomOnChar(wxKeyEvent &event)
{
switch (event.GetKeyCode())
{
case WXK_RETURN:
m_frame->UpdateASSCommandStringFromSrcTxtCtrl(GetValue());
break;
case WXK_TAB:
break; //do nothing
default:
//m_frame->SetTitle(wxString::Format(_T("Key: %d"), event.GetKeyCode()));
event.Skip(true);
}
//SetBackgroundColour(IsModified()? wxColour(0xFF, 0xFF, 0x99):*wxWHITE);
}
void ASSDrawSrcTxtCtrl::CustomOnText(wxCommandEvent &event)
{
//SetBackgroundColour(IsModified()? wxColour(0xFF, 0xFF, 0x99):*wxWHITE);
}
// ----------------------------------------------------------------------------
// ASSDrawTransformDlg
// ----------------------------------------------------------------------------
ASSDrawTransformDlg::ASSDrawTransformDlg(ASSDrawFrame* parent)
: wxDialog(parent, -1, wxString(_T("Transform")))
{
m_frame = parent;
wxBoxSizer* sizer_main = new wxBoxSizer(wxVERTICAL);
this->SetSizer(sizer_main);
wxBoxSizer* sizer_templates = new wxBoxSizer(wxHORIZONTAL);
sizer_main->Add(sizer_templates, 0, wxGROW|wxLEFT, 5);
sizer_templates->Add(new wxStaticText( this, -1, _("Templates"), __DPDS__ , 0 ),
0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
combo_templates = new wxComboBox( this, -1, combo_templatesStrings[0], __DPDS__ , 10, combo_templatesStrings, wxCB_READONLY );
sizer_templates->Add(combo_templates, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
wxFlexGridSizer* sizer_fields = new wxFlexGridSizer(3, 4, 0, 0);
sizer_main->Add(sizer_fields, 0, wxALIGN_CENTER_HORIZONTAL|wxLEFT, 5);
int flag_txtctrl = wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL;
int flag_statictxt = wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL;
sizer_fields->Add(new wxStaticText( this, -1, _("m11"), __DPDS__ , 0 ),
0, flag_statictxt, 5);
txtctrl_m11 = new wxTextCtrl( this, -1, _T("1.0"), __DPDS__ , wxTE_RIGHT );
sizer_fields->Add(txtctrl_m11, 0, flag_txtctrl, 5);
sizer_fields->Add(new wxStaticText( this, -1, _("m12"), __DPDS__ , 0 ),
0, flag_statictxt, 5);
txtctrl_m12 = new wxTextCtrl( this, -1, _T("0.0"), __DPDS__ , wxTE_RIGHT );
sizer_fields->Add(txtctrl_m12, 0, flag_txtctrl, 5);
sizer_fields->Add(new wxStaticText( this, -1, _("m21"), __DPDS__ , 0 ),
0, flag_statictxt, 5);
txtctrl_m21 = new wxTextCtrl( this, -1, _T("0.0"), __DPDS__ , wxTE_RIGHT );
sizer_fields->Add(txtctrl_m21, 0, flag_txtctrl, 5);
sizer_fields->Add(new wxStaticText( this, -1, _("m22"), __DPDS__ , 0 ),
0, flag_statictxt, 5);
txtctrl_m22 = new wxTextCtrl( this, -1, _T("1.0"), __DPDS__ , wxTE_RIGHT );
sizer_fields->Add(txtctrl_m22, 0, flag_txtctrl, 5);
sizer_fields->Add(new wxStaticText( this, -1, _("mx"), __DPDS__ , 0 ),
0, flag_statictxt, 5);
txtctrl_mx = new wxTextCtrl( this, -1, _T("0.0"), __DPDS__ , wxTE_RIGHT );
sizer_fields->Add(txtctrl_mx, 0, flag_txtctrl, 5);
sizer_fields->Add(new wxStaticText( this, -1, _("my"), __DPDS__ , 0 ),
0, flag_statictxt, 5);
txtctrl_my = new wxTextCtrl( this, -1, _T("0.0"), __DPDS__ , wxTE_RIGHT );
sizer_fields->Add(txtctrl_my, 0, flag_txtctrl, 5);
sizer_fields->Add(new wxStaticText( this, -1, _("nx"), __DPDS__ , 0 ),
0, flag_statictxt, 5);
txtctrl_nx = new wxTextCtrl( this, -1, _T("0.0"), __DPDS__ , wxTE_RIGHT );
sizer_fields->Add(txtctrl_nx, 0, flag_txtctrl, 5);
sizer_fields->Add(new wxStaticText( this, -1, _("ny"), __DPDS__ , 0 ),
0, flag_statictxt, 5);
txtctrl_ny = new wxTextCtrl( this, -1, _T("0.0"), __DPDS__ , wxTE_RIGHT );
sizer_fields->Add(txtctrl_ny, 0, flag_txtctrl, 5);
wxStaticBitmap* staticbmp = new wxStaticBitmap( this, -1, wxBITMAP(transform), wxDefaultPosition, wxSize(224, 56), 0 );
sizer_main->Add(staticbmp, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
wxStdDialogButtonSizer* sizer_stdbutt = new wxStdDialogButtonSizer;
sizer_main->Add(sizer_stdbutt, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
wxButton* button_ok = new wxButton( this, wxID_OK, _("&OK"), __DPDS__ , 0 );
sizer_stdbutt->AddButton(button_ok);
wxButton* button_cancel = new wxButton( this, wxID_CANCEL, _("&Cancel"), __DPDS__ , 0 );
sizer_stdbutt->AddButton(button_cancel);
sizer_stdbutt->Realize();
sizer_main->Fit(this);
}
void ASSDrawTransformDlg::OnTemplatesCombo(wxCommandEvent &event)
{
int pos = -1;
for (int i = 0; i < combo_templatesCount; i++)
if (combo_templatesStrings[i].IsSameAs(((wxComboBox *) event.GetEventObject())->GetValue()))
{
pos = i;
break;
}
if (pos == -1)
return;
txtctrl_m11->SetValue( wxString::Format(_T("%.1f"), combo_templatesValues[pos].f1) );
txtctrl_m12->SetValue( wxString::Format(_T("%.1f"), combo_templatesValues[pos].f2) );
txtctrl_m21->SetValue( wxString::Format(_T("%.1f"), combo_templatesValues[pos].f3) );
txtctrl_m22->SetValue( wxString::Format(_T("%.1f"), combo_templatesValues[pos].f4) );
txtctrl_mx->SetValue( wxString::Format(_T("%.1f"), combo_templatesValues[pos].f5) );
txtctrl_my->SetValue( wxString::Format(_T("%.1f"), combo_templatesValues[pos].f6) );
txtctrl_nx->SetValue( wxString::Format(_T("%.1f"), combo_templatesValues[pos].f7) );
txtctrl_ny->SetValue( wxString::Format(_T("%.1f"), combo_templatesValues[pos].f8) );
}
void ASSDrawTransformDlg::EndModal(int retCode)
{
if (retCode != wxID_OK)
{
wxDialog::EndModal(retCode);
return;
}
bool ok = true;
ok = ok && txtctrl_m11->GetValue().ToDouble( &xformvals.f1 );
ok = ok && txtctrl_m12->GetValue().ToDouble( &xformvals.f2 );
ok = ok && txtctrl_m21->GetValue().ToDouble( &xformvals.f3 );
ok = ok && txtctrl_m22->GetValue().ToDouble( &xformvals.f4 );
ok = ok && txtctrl_mx->GetValue().ToDouble( &xformvals.f5 );
ok = ok && txtctrl_my->GetValue().ToDouble( &xformvals.f6 );
ok = ok && txtctrl_nx->GetValue().ToDouble( &xformvals.f7 );
ok = ok && txtctrl_ny->GetValue().ToDouble( &xformvals.f8 );
if (ok)
wxDialog::EndModal(wxID_OK);
else
wxMessageBox(_T("One or more values entered are not real numbers.\nPlease fix."), _T("Value error"), wxOK | wxICON_INFORMATION, m_frame);
}
ASSDrawAboutDlg::ASSDrawAboutDlg(ASSDrawFrame *parent, unsigned timeout)
: wxDialog(parent, wxID_ANY, wxString(TITLE), __DPDS__ , wxSIMPLE_BORDER), time_out(timeout)
{
SetBackgroundColour(*wxWHITE);
htmlwin = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxSize(396, 200), wxHW_DEFAULT_STYLE | wxSIMPLE_BORDER);
htmlwin->SetPage(
_T("<html><body> \
<p>ASSDraw3 is a tool for designing shapes to be used in ASS subtitle file. \
<p>To add lines or curves, initiate the draw mode by clicking on the drawing tools. \
Then, either click on empty space or drag from an existing point to add the new lines/curves. \
Control points for Bezier curves are generated once you release the mouse button. \
<p>To modify shapes, drag their points (squares) and control points (circles) in the drag mode. \
<p><b>Some tips & tricks:</b> \
<ul> \
<li> Set background image by dragging image file from explorer onto the canvas \
<li> Use the Shapes Library to store your drawings \
<li> Ctrl-Z for undo, Ctrl-Y for redo \
<li> Use your mousewheel to zoom in/out (PageUp/PageDown keys work too) \
<li> Dragging with right mouse button moves the drawing and/or background image around. \
<li> Double clicking with right mouse button for popup menus. \
<li> Holding shift key while in the draw mode temporarily switches to the drag mode \
<li> The shapes origin (coordinate [0, 0] depicted by the small cross) is draggable \
</ul> \
<p><b>Acknowledgements:</b> \
<ul> \
<li> Maxim Shemanarev <a href=\"http://www.antigrain.com\">http://www.antigrain.com</a> for his Anti-Grain Geometry (AGG) graphic toolkit. \
<li> wxWidgets Project <a href=\"http://www.wxwidgets.org\">http://www.wxwidgets.org</a> for the ultracool GUI toolkit. \
<li> Adrian Secord <a href=\"http://mrl.nyu.edu/~ajsecord/index.html\">http://mrl.nyu.edu/~ajsecord/index.html</a> for wxAGG, that combines AGG and wxWidgets\
<li> jfs, ArchMageZeratul, RoRo and everyone at Aegisub's forum <a href=\"http://malakith.net/aegisub\">http://malakith.net/aegisub</a> for all suggestions and supports. \
</ul> \
<p>ai-chan recommends Aegisub for all your subtitle and typesetting needs! \
</body></html>")
);
htmlwin->Connect(wxEVT_COMMAND_HTML_LINK_CLICKED, wxHtmlLinkEventHandler(ASSDrawAboutDlg::OnURL), NULL, this);
wxFlexGridSizer *sizer = new wxFlexGridSizer(1);
sizer->AddGrowableCol(0);
//sizer->AddGrowableRow(1);
sizer->Add(new BigStaticBitmapCtrl(this, wxBITMAP(assdraw3_), *wxWHITE, this), 1, wxEXPAND);
sizer->Add(htmlwin, 1, wxLEFT | wxRIGHT, 2);
sizer->Add(new wxStaticText(this, wxID_ANY, wxString::Format(_T("Version: %s"), VERSION)), 1, wxEXPAND | wxALL, 2);
sizer->Add(new wxButton(this, wxID_OK), 0, wxALIGN_CENTER | wxBOTTOM, 10);
SetSizer(sizer);
sizer->Layout();
sizer->Fit(this);
Center();
//if (CanSetTransparent()) SetTransparent(0xCC);
timer.SetOwner(this);
Connect(wxEVT_TIMER, wxTimerEventHandler(ASSDrawAboutDlg::OnTimeout));
Connect(wxEVT_ENTER_WINDOW, wxMouseEventHandler(ASSDrawAboutDlg::OnMouseEnterWindow));
}
ASSDrawAboutDlg::~ASSDrawAboutDlg()
{
timer.Stop();
}
int ASSDrawAboutDlg::ShowModal()
{
if (time_out > 0)
timer.Start(time_out * 1000, true);
return wxDialog::ShowModal();
}
void ASSDrawAboutDlg::OnURL(wxHtmlLinkEvent &event)
{
wxString URL(event.GetLinkInfo().GetHref());
if (URL.StartsWith(_T("http://")))
::wxLaunchDefaultBrowser(URL);
else
event.Skip(true);
}
void ASSDrawAboutDlg::OnTimeout(wxTimerEvent& event)
{
if (IsShown())
EndModal(wxID_OK);
}
void ASSDrawAboutDlg::OnMouseEnterWindow(wxMouseEvent& event)
{
// if mouse enters this dialog, stop the timout timer
// and dialog will only close through user input
timer.Stop();
}
BEGIN_EVENT_TABLE(BigStaticBitmapCtrl, wxPanel)
EVT_PAINT(BigStaticBitmapCtrl::OnPaint)
EVT_MOTION (BigStaticBitmapCtrl::OnMouseMove)
EVT_LEFT_UP(BigStaticBitmapCtrl::OnMouseLeftUp)
EVT_LEFT_DOWN(BigStaticBitmapCtrl::OnMouseLeftDown)
END_EVENT_TABLE()
BigStaticBitmapCtrl::BigStaticBitmapCtrl(wxWindow *parent, wxBitmap bmap, wxColour bgcol, wxWindow *todrag)
: wxPanel(parent, wxID_ANY)
{
bitmap = bmap;
bgbrush = wxBrush(bgcol);
window_to_drag = todrag;
SetSize(bitmap.GetWidth(), bitmap.GetHeight());
Refresh();
}
BigStaticBitmapCtrl::~BigStaticBitmapCtrl()
{
}
void BigStaticBitmapCtrl::OnPaint(wxPaintEvent& event)
{
wxPaintDC dc(this);
dc.SetBackground(bgbrush);
dc.Clear();
dc.DrawBitmap(bitmap, wxPoint(0,0));
}
void BigStaticBitmapCtrl::OnMouseLeftDown(wxMouseEvent &event)
{
if (window_to_drag != NULL)
{
dragpoint = event.GetPosition();
}
CaptureMouse();
}
void BigStaticBitmapCtrl::OnMouseLeftUp(wxMouseEvent &event)
{
ReleaseMouse();
}
void BigStaticBitmapCtrl::OnMouseMove(wxMouseEvent &event)
{
if (window_to_drag != NULL && event.Dragging() && HasCapture())
{
wxPoint npoint(event.GetPosition());
wxPoint wndpos = window_to_drag->GetScreenPosition();
wxPoint thispos = this->GetScreenPosition();
//ReleaseMouse();
window_to_drag->Move(wndpos.x + npoint.x - dragpoint.x,
wndpos.y + npoint.y - dragpoint.y);
//CaptureMouse();
if (thispos == this->GetScreenPosition()) // if this ctrl did not move when window_to_drag moved
dragpoint = npoint;
}
event.Skip(true);
}