1 // Copyright (c) 2011, Thomas Goyne <plorkyeran@aegisub.org>
2 //
3 // Permission to use, copy, modify, and distribute this software for any
4 // purpose with or without fee is hereby granted, provided that the above
5 // copyright notice and this permission notice appear in all copies.
6 //
7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 //
15 // Aegisub Project http://www.aegisub.org/
16 
17 /// @file visual_tool_cross.cpp
18 /// @brief Crosshair double-click-to-position visual typesetting tool
19 /// @ingroup visual_ts
20 
21 #include "visual_tool_cross.h"
22 
23 #include "gl_text.h"
24 #include "include/aegisub/context.h"
25 #include "selection_controller.h"
26 #include "video_display.h"
27 
28 #include <libaegisub/color.h>
29 #include <libaegisub/format.h>
30 #include <libaegisub/make_unique.h>
31 
VisualToolCross(VideoDisplay * parent,agi::Context * context)32 VisualToolCross::VisualToolCross(VideoDisplay *parent, agi::Context *context)
33 : VisualTool<VisualDraggableFeature>(parent, context)
34 , gl_text(agi::make_unique<OpenGLText>())
35 {
36 	parent->SetCursor(wxCursor(wxCURSOR_BLANK));
37 }
38 
~VisualToolCross()39 VisualToolCross::~VisualToolCross() {
40 	parent->SetCursor(wxNullCursor);
41 }
42 
OnDoubleClick()43 void VisualToolCross::OnDoubleClick() {
44 	Vector2D d = ToScriptCoords(mouse_pos) - GetLinePosition(active_line);
45 
46 	for (auto line : c->selectionController->GetSelectedSet()) {
47 		Vector2D p1, p2;
48 		int t1, t2;
49 		if (GetLineMove(line, p1, p2, t1, t2)) {
50 			if (t1 > 0 || t2 > 0)
51 				SetOverride(line, "\\move", agi::format("(%s,%s,%d,%d)", Text(p1 + d), Text(p2 + d), t1, t2));
52 			else
53 				SetOverride(line, "\\move", agi::format("(%s,%s)", Text(p1 + d), Text(p2 + d)));
54 		}
55 		else
56 			SetOverride(line, "\\pos", "(" + Text(GetLinePosition(line) + d) + ")");
57 
58 		if (Vector2D org = GetLineOrigin(line))
59 			SetOverride(line, "\\org", "(" + Text(org + d) + ")");
60 	}
61 
62 	Commit(_("positioning"));
63 }
64 
Draw()65 void VisualToolCross::Draw() {
66 	if (!mouse_pos) return;
67 
68 	// Draw cross
69 	gl.SetInvert();
70 	gl.SetLineColour(*wxWHITE, 1.0, 1);
71 	float lines[] = {
72 		0.f, mouse_pos.Y(),
73 		video_res.X() + video_pos.X() * 2, mouse_pos.Y(),
74 		mouse_pos.X(), 0.f,
75 		mouse_pos.X(), video_res.Y() + video_pos.Y() * 2
76 	};
77 	gl.DrawLines(2, lines, 4);
78 	gl.ClearInvert();
79 
80 	std::string mouse_text = Text(ToScriptCoords(shift_down ? video_res - mouse_pos : mouse_pos));
81 
82 	int tw, th;
83 	gl_text->SetFont("Verdana", 12, true, false);
84 	gl_text->SetColour(agi::Color(255, 255, 255, 255));
85 	gl_text->GetExtent(mouse_text, tw, th);
86 
87 	// Place the text in the corner of the cross closest to the center of the video
88 	int dx = mouse_pos.X();
89 	int dy = mouse_pos.Y();
90 	if (dx > video_res.X() / 2)
91 		dx -= tw + 4;
92 	else
93 		dx += 4;
94 
95 	if (dy < video_res.Y() / 2)
96 		dy += 3;
97 	else
98 		dy -= th + 3;
99 
100 	gl_text->Print(mouse_text, dx, dy);
101 }
102 
Text(Vector2D v)103 std::string VisualToolCross::Text(Vector2D v) {
104 	return video_res.X() > script_res.X() ? v.Str() : v.DStr();
105 }
106