xue@0
|
1 /*
|
xue@0
|
2 Harmonic Visualiser
|
xue@0
|
3
|
xue@0
|
4 An audio file viewer and editor.
|
xue@0
|
5 Centre for Digital Music, Queen Mary, University of London.
|
xue@0
|
6 This file copyright 2011 Wen Xue.
|
xue@0
|
7
|
xue@0
|
8 This program is free software; you can redistribute it and/or
|
xue@0
|
9 modify it under the terms of the GNU General Public License as
|
xue@0
|
10 published by the Free Software Foundation; either version 2 of the
|
xue@0
|
11 License, or (at your option) any later version.
|
xue@0
|
12 */
|
xue@0
|
13 //---------------------------------------------------------------------------
|
xue@0
|
14
|
xue@0
|
15 #include <vcl.h>
|
xue@0
|
16
|
xue@0
|
17 #pragma hdrstop
|
xue@0
|
18
|
xue@0
|
19 #include "Navigator.h"
|
xue@0
|
20 #pragma package(smart_init)
|
xue@0
|
21 //---------------------------------------------------------------------------
|
xue@0
|
22 // ValidCtrCheck is used to assure that the components created do not have
|
xue@0
|
23 // any pure virtual functions.
|
xue@0
|
24 //
|
xue@0
|
25
|
xue@0
|
26 static inline void ValidCtrCheck(TNavigator *)
|
xue@0
|
27 {
|
xue@0
|
28 new TNavigator(NULL);
|
xue@0
|
29 }
|
xue@0
|
30 //---------------------------------------------------------------------------
|
xue@0
|
31 __fastcall TNavigator::TNavigator(TComponent* Owner)
|
xue@0
|
32 : TCustomControl(Owner)
|
xue@0
|
33 {
|
xue@0
|
34 x1=y1=0;
|
xue@0
|
35 x2=y2=1;
|
xue@0
|
36 FOnBackground=0;
|
xue@0
|
37 BkgBmp=new Graphics::TBitmap;
|
xue@0
|
38 }
|
xue@0
|
39
|
xue@0
|
40 __fastcall TNavigator::~TNavigator()
|
xue@0
|
41 {
|
xue@0
|
42 delete BkgBmp;
|
xue@0
|
43 }
|
xue@0
|
44
|
xue@0
|
45 void TNavigator::DrawArea()
|
xue@0
|
46 {
|
xue@0
|
47 Canvas->Brush->Style=bsClear;
|
xue@0
|
48 Canvas->Pen->Mode=pmXor;
|
xue@0
|
49 Canvas->Pen->Color=AreaColorX;
|
xue@0
|
50 X1=x1*Width, X2=x2*Width, Y1=y1*Height, Y2=y2*Height;
|
xue@0
|
51 if (X1+1<X2 && Y1+1<Y2)
|
xue@0
|
52 Canvas->Rectangle(X1, Y1, X2, Y2);
|
xue@0
|
53 else if (X1+1>=X2)
|
xue@0
|
54 {
|
xue@0
|
55 Canvas->MoveTo(X1, Y1);
|
xue@0
|
56 Canvas->LineTo(X1, Y2);
|
xue@0
|
57 }
|
xue@0
|
58 else
|
xue@0
|
59 {
|
xue@0
|
60 Canvas->MoveTo(X1, Y1);
|
xue@0
|
61 Canvas->LineTo(X2, Y1);
|
xue@0
|
62 }
|
xue@0
|
63 }
|
xue@0
|
64
|
xue@0
|
65 TNavigatorHitTest TNavigator::HitTest(int X, int Y)
|
xue@0
|
66 {
|
xue@0
|
67 int Xa=1, Ya=1; //borderouter
|
xue@0
|
68 int Xb=1, Yb=1; //borderinner
|
xue@0
|
69 if (X2-X1<=3) Xb=0;
|
xue@0
|
70 if (Y2-Y1<=3) Yb=0;
|
xue@0
|
71 if (X2-X1<=1) Xb=-1;
|
xue@0
|
72 if (Y2-Y1<=1) Yb=-1;
|
xue@0
|
73
|
xue@0
|
74 TNavigatorHitTest XTest, YTest;
|
xue@0
|
75
|
xue@0
|
76 if (X<X1-Xa || X>X2+Xa) XTest=htOuter;
|
xue@0
|
77 else if (X1-Xa<=X && X<=X1+Xb) XTest=htLeft;
|
xue@0
|
78 else if (X1+Xb<X && X<X2-Xb) XTest=htInner;
|
xue@0
|
79 else XTest=htRight;
|
xue@0
|
80
|
xue@0
|
81 if (Y<Y1-Ya || Y>Y2+Ya) YTest=htOuter;
|
xue@0
|
82 else if (Y1-Ya<=Y && Y<=Y1+Yb) YTest=htTop;
|
xue@0
|
83 else if (Y1+Yb<Y & Y<Y2-Yb) YTest=htInner;
|
xue@0
|
84 else YTest=htBottom;
|
xue@0
|
85
|
xue@0
|
86 if (XTest==htInner && YTest==htInner)
|
xue@0
|
87 return htInner;
|
xue@0
|
88 if (YTest==htInner && XTest!=htOuter)
|
xue@0
|
89 return XTest;
|
xue@0
|
90 if (XTest==htInner && YTest!=htOuter)
|
xue@0
|
91 return YTest;
|
xue@0
|
92 return htOuter;
|
xue@0
|
93 }
|
xue@0
|
94
|
xue@0
|
95 void __fastcall TNavigator::MouseDown(TMouseButton Button, TShiftState Shift, int X, int Y)
|
xue@0
|
96 {
|
xue@0
|
97 if (Button==mbLeft)
|
xue@0
|
98 {
|
xue@0
|
99 X0=X, Y0=Y;
|
xue@0
|
100 x01=x1, x02=x2, y01=y1, y02=y2;
|
xue@0
|
101
|
xue@0
|
102 FMouseAction=maNoAction;
|
xue@0
|
103
|
xue@0
|
104 FHitTest=HitTest(X, Y);
|
xue@0
|
105 if (FHitTest!=htOuter) FMouseAction=maMove;
|
xue@0
|
106
|
xue@0
|
107 if (Shift.Contains(ssCtrl))
|
xue@0
|
108 {
|
xue@0
|
109 switch (FHitTest)
|
xue@0
|
110 {
|
xue@0
|
111 case htInner:
|
xue@0
|
112 break;
|
xue@0
|
113 case htLeft:
|
xue@0
|
114 case htTop:
|
xue@0
|
115 case htRight:
|
xue@0
|
116 case htBottom:
|
xue@0
|
117 case htTopLeft:
|
xue@0
|
118 case htTopRight:
|
xue@0
|
119 case htBottomRight:
|
xue@0
|
120 case htBottomLeft:
|
xue@0
|
121 FMouseAction=maSize; break;
|
xue@0
|
122 }
|
xue@0
|
123 }
|
xue@0
|
124
|
xue@0
|
125 if (FMouseAction==maMove)
|
xue@0
|
126 Cursor=crSizeAll;
|
xue@0
|
127 else if (FMouseAction==maSize)
|
xue@0
|
128 {
|
xue@0
|
129 if (FHitTest==htLeft || FHitTest==htRight)
|
xue@0
|
130 Cursor=crSizeWE;
|
xue@0
|
131 else
|
xue@0
|
132 Cursor=crSizeNS;
|
xue@0
|
133 }
|
xue@0
|
134 ::SetCursor(Screen->Cursors[Cursor]);
|
xue@0
|
135 }
|
xue@0
|
136 if (Button==mbRight)
|
xue@0
|
137 {
|
xue@0
|
138 TPoint P=ClientToScreen(TPoint((X1+X2)/2, (Y1+Y2)/2));
|
xue@0
|
139 SetCursorPos(P.x, P.y);
|
xue@0
|
140 }
|
xue@0
|
141 }
|
xue@0
|
142
|
xue@0
|
143 void __fastcall TNavigator::MouseMove(TShiftState Shift, int X, int Y)
|
xue@0
|
144 {
|
xue@0
|
145 if (Shift.Contains(ssLeft))
|
xue@0
|
146 {
|
xue@0
|
147 double destx1=x1, destx2=x2, desty1=y1, desty2=y2;
|
xue@0
|
148
|
xue@0
|
149 int dX=X-X0;
|
xue@0
|
150 int dY=Y-Y0;
|
xue@0
|
151
|
xue@0
|
152 double dx=dX*1.0/Width;
|
xue@0
|
153 double dy=dY*1.0/Height;
|
xue@0
|
154
|
xue@0
|
155 if (FMouseAction==maMove)
|
xue@0
|
156 {
|
xue@0
|
157 if (x01+dx<0) dx=-x01;
|
xue@0
|
158 if (x02+dx>1) dx=1-x02;
|
xue@0
|
159 if (y01+dy<0) dy=-y01;
|
xue@0
|
160 if (y02+dy>1) dy=1-y02;
|
xue@0
|
161 destx1=x01+dx;
|
xue@0
|
162 destx2=x02+dx;
|
xue@0
|
163 desty1=y01+dy;
|
xue@0
|
164 desty2=y02+dy;
|
xue@0
|
165 }
|
xue@0
|
166 else if (FMouseAction==maSize)
|
xue@0
|
167 {
|
xue@0
|
168 switch(FHitTest)
|
xue@0
|
169 {
|
xue@0
|
170 case htLeft:
|
xue@0
|
171 if (x01+dx<0) dx=-x01;
|
xue@0
|
172 if (x01+dx>1) dx=1-x01;
|
xue@0
|
173 destx1=x01+dx;
|
xue@0
|
174 if (destx1>x02) {destx2=destx1; destx1=x02;}
|
xue@0
|
175 break;
|
xue@0
|
176 case htRight:
|
xue@0
|
177 if (x02+dx<0) dx=-x02;
|
xue@0
|
178 if (x02+dx>1) dx=1-x02;
|
xue@0
|
179 destx2=x02+dx;
|
xue@0
|
180 if (x01>destx2) {destx1=destx2; destx2=x01;}
|
xue@0
|
181 break;
|
xue@0
|
182 case htTop:
|
xue@0
|
183 if (y01+dy<0) dy=-y01;
|
xue@0
|
184 if (y01+dy>1) dy=1-y01;
|
xue@0
|
185 desty1=y01+dy;
|
xue@0
|
186 if (desty1>y02) {desty2=desty1; desty1=y02;}
|
xue@0
|
187 break;
|
xue@0
|
188 case htBottom:
|
xue@0
|
189 if (y02+dy<0) dy=-y02;
|
xue@0
|
190 if (y02+dy>1) dy=1-y02;
|
xue@0
|
191 desty2=y02+dy;
|
xue@0
|
192 if (y01>desty2) {desty1=desty2; desty2=y01;}
|
xue@0
|
193 break;
|
xue@0
|
194 }
|
xue@0
|
195 }
|
xue@0
|
196
|
xue@0
|
197 if (destx1!=x1 || destx2!=x2 || desty1!=y1 || desty2!=y2)
|
xue@0
|
198 {
|
xue@0
|
199 SetArea(destx1, destx2, desty1, desty2);
|
xue@0
|
200 FOnAreaChange(this);
|
xue@0
|
201 }
|
xue@0
|
202 }
|
xue@0
|
203 else if (Shift.Contains(ssCtrl))
|
xue@0
|
204 {
|
xue@0
|
205 TCursor NewCursor;
|
xue@0
|
206 FHitTest=HitTest(X, Y);
|
xue@0
|
207 if (FHitTest==htLeft || FHitTest==htRight)
|
xue@0
|
208 NewCursor=crSizeWE;
|
xue@0
|
209 else if (FHitTest==htTop || FHitTest==htBottom)
|
xue@0
|
210 NewCursor=crSizeNS;
|
xue@0
|
211 else if (FHitTest==htInner)
|
xue@0
|
212 NewCursor=crSizeAll;
|
xue@0
|
213 else
|
xue@0
|
214 NewCursor=crArrow;
|
xue@0
|
215 if (Cursor!=NewCursor)
|
xue@0
|
216 {
|
xue@0
|
217 Cursor=NewCursor;
|
xue@0
|
218 ::SetCursor(Screen->Cursors[Cursor]);
|
xue@0
|
219 }
|
xue@0
|
220 }
|
xue@0
|
221 else
|
xue@0
|
222 {
|
xue@0
|
223 if (Cursor!=crArrow)
|
xue@0
|
224 {
|
xue@0
|
225 Cursor=crArrow;
|
xue@0
|
226 ::SetCursor(Screen->Cursors[Cursor]);
|
xue@0
|
227 }
|
xue@0
|
228 }
|
xue@0
|
229 }
|
xue@0
|
230
|
xue@0
|
231 void __fastcall TNavigator::MouseUp(TMouseButton Button, TShiftState, int, int)
|
xue@0
|
232 {
|
xue@0
|
233 if (Button==mbLeft)
|
xue@0
|
234 {
|
xue@0
|
235 Cursor=crArrow;
|
xue@0
|
236 ::SetCursor(Screen->Cursors[Cursor]);
|
xue@0
|
237 }
|
xue@0
|
238 }
|
xue@0
|
239
|
xue@0
|
240 void __fastcall TNavigator::Paint()
|
xue@0
|
241 {
|
xue@0
|
242 Canvas->CopyRect(ClientRect, BkgBmp->Canvas, ClientRect);// if (FOnBackground) FOnBackground(this);
|
xue@0
|
243 DrawArea();
|
xue@0
|
244 }
|
xue@0
|
245
|
xue@0
|
246 void __fastcall TNavigator::Resize()
|
xue@0
|
247 {
|
xue@0
|
248 BkgBmp->Width=Width;
|
xue@0
|
249 BkgBmp->Height=Height;
|
xue@0
|
250 if (FOnBackground) FOnBackground(this);
|
xue@0
|
251 Invalidate();
|
xue@0
|
252 TControl::Resize();
|
xue@0
|
253 }
|
xue@0
|
254
|
xue@0
|
255 void TNavigator::SetArea(double ax1, double ax2, double ay1, double ay2)
|
xue@0
|
256 {
|
xue@0
|
257 if (x1==ax1 && x2==ax2 && y1==ay1 && y2==ay2) return;
|
xue@0
|
258 DrawArea();
|
xue@0
|
259 x1=ax1, x2=ax2, y1=ay1, y2=ay2;
|
xue@0
|
260 DrawArea();
|
xue@0
|
261 }
|
xue@0
|
262 //---------------------------------------------------------------------------
|
xue@0
|
263 namespace Navigator
|
xue@0
|
264 {
|
xue@0
|
265 void __fastcall PACKAGE Register()
|
xue@0
|
266 {
|
xue@0
|
267 TComponentClass classes[1] = {__classid(TNavigator)};
|
xue@0
|
268 RegisterComponents("Samples", classes, 0);
|
xue@0
|
269 }
|
xue@0
|
270 }
|
xue@0
|
271 //---------------------------------------------------------------------------
|