aboutsummaryrefslogtreecommitdiffstats
path: root/vstgui/vstgui.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'vstgui/vstgui.cpp')
-rw-r--r--vstgui/vstgui.cpp3996
1 files changed, 3996 insertions, 0 deletions
diff --git a/vstgui/vstgui.cpp b/vstgui/vstgui.cpp
new file mode 100644
index 0000000..ab52007
--- /dev/null
+++ b/vstgui/vstgui.cpp
@@ -0,0 +1,3996 @@
+/* ----------------------------------------------------------------------------
+ * VSTGUI for X11/LV2/PNG
+ * Author: Dave Robillard
+ * Released under the revised BSD license, as below
+ * ----------------------------------------------------------------------------
+ *
+ * Based on:
+ * ----------------------------------------------------------------------------
+ * VSTGUIL: Graphical User Interface Framework for VST plugins on LINUX
+ * Version: 0.1, Date: 2007/01/21
+ * Author: kRAkEn/gORe
+ *
+ * Which was based on:
+ * ----------------------------------------------------------------------------
+ * VSTGUI: Graphical User Interface Framework for VST plugins
+ * Version 3.0 $Date: 2005/08/12 12:45:00 $
+ * ----------------------------------------------------------------------------
+ * VSTGUI LICENSE
+ * 2004, Steinberg Media Technologies, 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 Steinberg Media Technologies 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ * ----------------------------------------------------------------------------
+ */
+
+#include <cstdio>
+#include <cstdlib>
+#include <cmath>
+#include <iostream>
+#include <string.h>
+
+#include "vstgui.h"
+#include "audioeffectx.h"
+#include "vstkeycode.h"
+
+//-----------------------------------------------------------------------------
+// Some defines
+//-----------------------------------------------------------------------------
+#ifdef DEBUG
+ #define DBG(x) std::cout << x << std::endl;
+ #define assertfalse assert (false);
+#else
+ #define DBG(x)
+ #define assertfalse
+#endif
+
+#define USE_ALPHA_BLEND 0
+#define USE_CLIPPING_DRAWRECT 1
+#define NEW_UPDATE_MECHANISM 1
+
+
+//-----------------------------------------------------------------------------
+// our global display
+Display* display = 0;
+
+
+//-----------------------------------------------------------------------------
+// AEffGUIEditor Implementation
+//-----------------------------------------------------------------------------
+#define kIdleRate 100 // host idle rate in ms
+#define kIdleRate2 50
+#define kIdleRateMin 4 // minimum time between 2 idles in ms
+
+//-----------------------------------------------------------------------------
+VstInt32 AEffGUIEditor::knobMode = kCircularMode;
+
+//-----------------------------------------------------------------------------
+AEffGUIEditor::AEffGUIEditor (AudioEffect* effect)
+: AEffEditor (effect),
+ lLastTicks (0),
+ inIdleStuff (false),
+ bundlePath(NULL),
+ frame (0)
+{
+ rect.left = rect.top = rect.right = rect.bottom = 0;
+ lLastTicks = getTicks ();
+
+ effect->setEditor (this);
+}
+
+//-----------------------------------------------------------------------------
+AEffGUIEditor::~AEffGUIEditor ()
+{
+}
+
+//-----------------------------------------------------------------------------
+void AEffGUIEditor::setParameter (VstInt32 index, float value)
+{}
+
+//-----------------------------------------------------------------------------
+void AEffGUIEditor::beginEdit (VstInt32 index)
+{
+ ((AudioEffectX*)effect)->beginEdit (index);
+}
+
+//-----------------------------------------------------------------------------
+void AEffGUIEditor::endEdit (VstInt32 index)
+{
+ ((AudioEffectX*)effect)->endEdit (index);
+}
+
+//-----------------------------------------------------------------------------
+#if VST_2_1_EXTENSIONS
+long AEffGUIEditor::onKeyDown (VstKeyCode& keyCode)
+{
+ return frame && frame->onKeyDown (keyCode) == 1 ? 1 : 0;
+}
+
+//-----------------------------------------------------------------------------
+long AEffGUIEditor::onKeyUp (VstKeyCode& keyCode)
+{
+ return frame && frame->onKeyUp (keyCode) == 1 ? 1 : 0;
+}
+
+//-----------------------------------------------------------------------------
+long AEffGUIEditor::setKnobMode (VstInt32 val)
+{
+ knobMode = val;
+ return 1;
+}
+
+//-----------------------------------------------------------------------------
+bool AEffGUIEditor::onWheel (float distance)
+{
+/*
+ if (frame)
+ {
+ CDrawContext context (frame, NULL, systemWindow);
+ CPoint where;
+ context.getMouseLocation (where);
+ return frame->onWheel (&context, where, distance);
+ }
+*/
+ return false;
+}
+#endif
+
+//-----------------------------------------------------------------------------
+long AEffGUIEditor::getRect (ERect **ppErect)
+{
+ *ppErect = &rect;
+ return 1;
+}
+
+//-----------------------------------------------------------------------------
+void AEffGUIEditor::idle ()
+{
+ if (inIdleStuff)
+ return;
+
+ AEffEditor::idle ();
+ if (frame)
+ frame->idle ();
+}
+
+//-----------------------------------------------------------------------------
+void AEffGUIEditor::wait (unsigned int ms)
+{
+ usleep (ms * 1000);
+}
+
+//-----------------------------------------------------------------------------
+unsigned int AEffGUIEditor::getTicks ()
+{
+ return _getTicks ();
+}
+
+//-----------------------------------------------------------------------------
+void AEffGUIEditor::doIdleStuff ()
+{
+ // get the current time
+ unsigned int currentTicks = getTicks ();
+
+ // YG TEST idle ();
+ if (currentTicks < lLastTicks)
+ {
+ wait (kIdleRateMin);
+
+ currentTicks += kIdleRateMin;
+ if (currentTicks < lLastTicks - kIdleRate2)
+ return;
+ }
+
+ idle ();
+
+ // save the next time
+ lLastTicks = currentTicks + kIdleRate;
+
+ inIdleStuff = true;
+
+ if (effect)
+ effect->masterIdle ();
+
+ inIdleStuff = false;
+}
+
+void AEffGUIEditor::update ()
+{
+ if (frame)
+ frame->invalidate (CRect (0, 0, rect.right, rect.bottom));
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+//---For Debugging------------------------
+#if DEBUG
+long gNbCBitmap = 0;
+long gNbCView = 0;
+long gNbCDrawContext = 0;
+long gNbCOffscreenContext = 0;
+long gBitmapAllocation = 0;
+long gNbDC = 0;
+#include <stdarg.h>
+void DebugPrint (const char *format, ...);
+void DebugPrint (const char *format, ...)
+{
+ char string[300];
+ va_list marker;
+ va_start (marker, format);
+ vsprintf (string, format, marker);
+ if (!strcmp(string, ""))
+ strcpy (string, "Empty string\n");
+ fprintf (stderr, string);
+}
+#endif
+//---End For Debugging------------------------
+
+#include <assert.h>
+#include <time.h>
+#include <stdlib.h>
+#include <math.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#define XDRAWPARAM display, (Window)pWindow, (GC) pSystemContext
+#define XWINPARAM display, (Window)pFrame->getWindow()
+#define XGCPARAM display, (GC) pSystemContext
+
+// #define XDRAWPARAM display, (Window)pWindow, (GC)pSystemContext
+// #define XWINPARAM display, (Window)pWindow
+// #define XGCPARAM display, (GC)pSystemContext
+
+// init the static variable about font
+bool gFontInit = false;
+XFontStruct *gFontStructs[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+struct SFontTable { const char* name; const char* string; };
+
+static SFontTable gFontTable[] = {
+ {"SystemFont", "-*-fixed-*-*-*--12-*-*-*-*-*-*-*"}, // kSystemFont
+ {"NormalFontVeryBig", "-*-fixed-*-*-*--18-*-*-*-*-*-*-*"}, // kNormalFontVeryBig
+ {"NormalFontBig", "-*-fixed-*-*-*--18-*-*-*-*-*-*-*"}, // kNormalFontBig
+ {"NormalFont", "-*-fixed-*-*-*--12-*-*-*-*-*-*-*"}, // kNormalFont
+ {"NormalFontSmall", "-*-courier-*-*-*--10-*-*-*-*-*-*-*"}, // kNormalFontSmall
+ {"NormalFontSmaller", "-*-courier-*-*-*--9-*-*-*-*-*-*-*"}, // kNormalFontSmaller
+ {"NormalFontVerySmall", "-*-courier-*-*-*--8-*-*-*-*-*-*-*"}, // kNormalFontVerySmall
+ {"SymbolFont", "-*-fixed-*-*-*--12-*-*-*-*-*-*-*"} // kSymbolFont
+};
+
+long gStandardFontSize[] = { 12, 18, 18, 12, 10, 9, 8, 13 };
+
+// declaration of different local functions
+static long convertPoint2Angle (CPoint &pm, CPoint &pt);
+
+// stuff for color
+long CDrawContext::nbNewColor = 0;
+
+//-----------------------------------------------------------------------------
+bool CRect::pointInside (const CPoint& where) const
+{
+ return where.h >= left && where.h < right && where.v >= top && where.v < bottom;
+}
+
+//-----------------------------------------------------------------------------
+bool CRect::isEmpty () const
+{
+ if (right <= left)
+ return true;
+ if (bottom <= top)
+ return true;
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+void CRect::bound (const CRect& rect)
+{
+ if (left < rect.left)
+ left = rect.left;
+ if (top < rect.top)
+ top = rect.top;
+ if (right > rect.right)
+ right = rect.right;
+ if (bottom > rect.bottom)
+ bottom = rect.bottom;
+ if (bottom < top)
+ bottom = top;
+ if (right < left)
+ right = left;
+}
+
+namespace VSTGUI {
+
+CColor kTransparentCColor = {255, 255, 255, 0};
+CColor kBlackCColor = { 0, 0, 0, 255};
+CColor kWhiteCColor = {255, 255, 255, 255};
+CColor kGreyCColor = {127, 127, 127, 255};
+CColor kRedCColor = {255, 0, 0, 255};
+CColor kGreenCColor = { 0, 255, 0, 255};
+CColor kBlueCColor = { 0, 0, 255, 255};
+CColor kYellowCColor = {255, 255, 0, 255};
+CColor kMagentaCColor = {255, 0, 255, 255};
+CColor kCyanCColor = { 0, 255, 255, 255};
+
+#define kDragDelay 0
+
+//-----------------------------------------------------------------------------
+// CDrawContext Implementation
+//-----------------------------------------------------------------------------
+/**
+ * CDrawContext constructor.
+ * @param inFrame the parent CFrame
+ * @param inSystemContext the platform system context, can be NULL
+ * @param inWindow the platform window object
+ */
+CDrawContext::CDrawContext (CFrame *inFrame, void *inSystemContext, void *inWindow)
+: pSystemContext (inSystemContext)
+, pWindow (inWindow)
+, pFrame (inFrame)
+, fontSize (-1)
+, fontStyle (0)
+, fontId (kNumStandardFonts)
+, frameWidth (0)
+, lineStyle (kLineOnOffDash)
+, drawMode (kAntialias)
+{
+#if DEBUG
+ gNbCDrawContext++;
+#endif
+
+ // initialize values
+ if (pFrame)
+ pFrame->getViewSize (clipRect);
+ else
+ clipRect (0, 0, 1000, 1000);
+
+ const CColor notInitalized = {0, 0, 0, 0};
+ frameColor = notInitalized;
+ fillColor = notInitalized;
+ fontColor = notInitalized;
+
+ // offsets use by offscreen
+ offset (0, 0);
+ offsetScreen (0, 0);
+
+ // set the current font
+ if (pSystemContext)
+ {
+ // set the default values
+ setFont (kNormalFont);
+ setFrameColor (kWhiteCColor);
+ setLineStyle (kLineSolid);
+ setLineWidth (1);
+ setFont (kSystemFont);
+ setDrawMode (kCopyMode);
+ }
+}
+
+//-----------------------------------------------------------------------------
+CDrawContext::~CDrawContext ()
+{
+#if DEBUG
+ gNbCDrawContext--;
+#endif
+}
+
+//-----------------------------------------------------------------------------
+void CDrawContext::setLineStyle (CLineStyle style)
+{
+ if (lineStyle == style)
+ return;
+
+ lineStyle = style;
+
+ long line_width;
+ long line_style;
+ if (frameWidth == 1)
+ line_width = 0;
+ else
+ line_width = frameWidth;
+
+ switch (lineStyle)
+ {
+ case kLineOnOffDash:
+ line_style = LineOnOffDash;
+ break;
+ default:
+ line_style = LineSolid;
+ break;
+ }
+
+ XSetLineAttributes (XGCPARAM, line_width, line_style, CapNotLast, JoinRound);
+}
+
+//-----------------------------------------------------------------------------
+void CDrawContext::setLineWidth (CCoord width)
+{
+ if (frameWidth == width)
+ return;
+
+ frameWidth = width;
+
+ setLineStyle (lineStyle);
+}
+
+//-----------------------------------------------------------------------------
+void CDrawContext::setDrawMode (CDrawMode mode)
+{
+ if (drawMode == mode)
+ return;
+
+ drawMode = mode;
+
+ long iMode = 0;
+ switch (drawMode)
+ {
+ case kXorMode :
+ iMode = GXinvert;
+ break;
+ case kOrMode :
+ iMode = GXor;
+ break;
+ default:
+ iMode = GXcopy;
+ }
+
+ ((XGCValues*)pSystemContext)->function = iMode;
+
+ XChangeGC (XGCPARAM, GCFunction, (XGCValues*)pSystemContext);
+}
+
+//------------------------------------------------------------------------------
+void CDrawContext::setClipRect (const CRect &clip)
+{
+ CRect _clip (clip);
+ _clip.offset (offset.h, offset.v);
+
+ if (clipRect == _clip)
+ return;
+
+ clipRect = _clip;
+
+ XRectangle r;
+ r.x = 0;
+ r.y = 0;
+ r.width = clipRect.right - clipRect.left + 1;
+ r.height = clipRect.bottom - clipRect.top + 1;
+
+ XSetClipRectangles (XGCPARAM, clipRect.left, clipRect.top, &r, 1, Unsorted);
+}
+
+//------------------------------------------------------------------------------
+void CDrawContext::resetClipRect ()
+{
+ CRect newClip;
+ if (pFrame)
+ pFrame->getViewSize (newClip);
+ else
+ newClip (0, 0, 1000, 1000);
+
+ setClipRect (newClip);
+
+ clipRect = newClip;
+}
+
+//-----------------------------------------------------------------------------
+void CDrawContext::moveTo (const CPoint &_point)
+{
+ CPoint point (_point);
+ point.offset (offset.h, offset.v);
+
+ penLoc = point;
+}
+
+//-----------------------------------------------------------------------------
+void CDrawContext::lineTo (const CPoint& _point)
+{
+ CPoint point (_point);
+ point.offset (offset.h, offset.v);
+
+ CPoint start (penLoc);
+ CPoint end (point);
+ if (start.h == end.h)
+ {
+ if (start.v < -5)
+ start.v = -5;
+ else if (start.v > 10000)
+ start.v = 10000;
+
+ if (end.v < -5)
+ end.v = -5;
+ else if (end.v > 10000)
+ end.v = 10000;
+ }
+ if (start.v == end.v)
+ {
+ if (start.h < -5)
+ start.h = -5;
+ else if (start.h > 10000)
+ start.h = 10000;
+
+ if (end.h < -5)
+ end.h = -5;
+ else if (end.h > 10000)
+ end.h = 10000;
+ }
+
+ XDrawLine (XDRAWPARAM, start.h, start.v, end.h, end.v);
+
+ // keep trace of the new position
+ penLoc = point;
+}
+
+//-----------------------------------------------------------------------------
+void CDrawContext::drawLines (const CPoint* points, const long& numLines)
+{
+ // default implementation, when no platform optimized code is implemented
+ for (long i = 0; i < numLines * 2; i+=2)
+ {
+ moveTo (points[i]);
+ lineTo (points[i+1]);
+ }
+}
+
+//-----------------------------------------------------------------------------
+void CDrawContext::drawPolygon (const CPoint *pPoints, long numberOfPoints, const CDrawStyle drawStyle)
+{
+ if (drawStyle == kDrawFilled || drawStyle == kDrawFilledAndStroked)
+ fillPolygon (pPoints, numberOfPoints);
+ if (drawStyle == kDrawStroked || drawStyle == kDrawFilledAndStroked)
+ polyLine (pPoints, numberOfPoints);
+}
+
+//-----------------------------------------------------------------------------
+void CDrawContext::polyLine (const CPoint *pPoints, long numberOfPoints)
+{
+ XPoint* pt = (XPoint*)malloc (numberOfPoints * sizeof (XPoint));
+ if (!pt)
+ return;
+ for (long i = 0; i < numberOfPoints; i++)
+ {
+ pt[i].x = (short)pPoints[i].h + offset.h;
+ pt[i].y = (short)pPoints[i].v + offset.v;
+ }
+
+ XDrawLines (XDRAWPARAM, pt, numberOfPoints, CoordModeOrigin);
+
+ free (pt);
+}
+
+//-----------------------------------------------------------------------------
+void CDrawContext::fillPolygon (const CPoint *pPoints, long numberOfPoints)
+{
+ // convert the points
+ XPoint* pt = (XPoint*)malloc (numberOfPoints * sizeof (XPoint));
+ if (!pt)
+ return;
+ for (long i = 0; i < numberOfPoints; i++)
+ {
+ pt[i].x = (short)pPoints[i].h + offset.h;
+ pt[i].y = (short)pPoints[i].v + offset.v;
+ }
+
+ XFillPolygon (XDRAWPARAM, pt, numberOfPoints, Convex, CoordModeOrigin);
+
+ free (pt);
+}
+
+//-----------------------------------------------------------------------------
+void CDrawContext::drawRect (const CRect &_rect, const CDrawStyle drawStyle)
+{
+ CRect rect (_rect);
+ rect.offset (offset.h, offset.v);
+
+ XDrawRectangle (XDRAWPARAM, rect.left, rect.top, rect.width (), rect.height ());
+}
+
+//-----------------------------------------------------------------------------
+void CDrawContext::fillRect (const CRect &_rect)
+{
+ CRect rect (_rect);
+ rect.offset (offset.h, offset.v);
+
+ // Don't draw boundary
+ XFillRectangle (XDRAWPARAM, rect.left + 1, rect.top + 1, rect.width () - 1, rect.height () - 1);
+}
+
+//-----------------------------------------------------------------------------
+void CDrawContext::drawEllipse (const CRect &_rect, const CDrawStyle drawStyle)
+{
+ CPoint point (_rect.left + (_rect.right - _rect.left) / 2, _rect.top);
+ drawArc (_rect, point, point);
+}
+
+//-----------------------------------------------------------------------------
+void CDrawContext::fillEllipse (const CRect &_rect)
+{
+ CRect rect (_rect);
+ rect.offset (offset.h, offset.v);
+
+ // Don't draw boundary
+ CPoint point (_rect.left + ((_rect.right - _rect.left) / 2), _rect.top);
+ fillArc (_rect, point, point);
+}
+
+//-----------------------------------------------------------------------------
+void CDrawContext::drawPoint (const CPoint &_point, CColor color)
+{
+ CPoint point (_point);
+
+ CColor oldframecolor = frameColor;
+ setFrameColor (color);
+
+ XDrawPoint (XDRAWPARAM, point.h, point.v);
+
+ setFrameColor (oldframecolor);
+}
+
+//-----------------------------------------------------------------------------
+CColor CDrawContext::getPoint (const CPoint& _point)
+{
+// CPoint point (_point);
+// point.offset (offset.h, offset.v);
+
+ assertfalse // not implemented !
+
+ CColor color = kBlackCColor;
+ return color;
+}
+
+//-----------------------------------------------------------------------------
+void CDrawContext::floodFill (const CPoint& _start)
+{
+// CPoint start (_start);
+// start.offset (offset.h, offset.v);
+
+ assertfalse // not implemented !
+}
+
+//-----------------------------------------------------------------------------
+void CDrawContext::drawArc (const CRect &_rect, const float _startAngle, const float _endAngle, const CDrawStyle drawStyle) // in degree
+{
+ CRect rect (_rect);
+ rect.offset (offset.h, offset.v);
+
+ XDrawArc (XDRAWPARAM, rect.left, rect.top, rect.width (), rect.height (),
+ (int) _startAngle * 64, (int) _endAngle * 64);
+}
+
+//-----------------------------------------------------------------------------
+void CDrawContext::drawArc (const CRect &_rect, const CPoint &_point1, const CPoint &_point2)
+{
+ CRect rect (_rect);
+ rect.offset (offset.h, offset.v);
+ CPoint point1 (_point1);
+ point1.offset (offset.h, offset.v);
+ CPoint point2 (_point2);
+ point2.offset (offset.h, offset.v);
+
+ int angle1, angle2;
+ if ((point1.v == point2.v) && (point1.h == point2.h))
+ {
+ angle1 = 0;
+ angle2 = 23040; // 360 * 64
+ }
+ else
+ {
+ CPoint pm ((rect.left + rect.right) / 2, (rect.top + rect.bottom) / 2);
+ angle1 = convertPoint2Angle (pm, point1);
+ angle2 = convertPoint2Angle (pm, point2) - angle1;
+ if (angle2 < 0)
+ angle2 += 23040; // 360 * 64
+ }
+
+ XDrawArc (XDRAWPARAM, rect.left, rect.top, rect.width (), rect.height (),
+ angle1, angle2);
+}
+
+//-----------------------------------------------------------------------------
+void CDrawContext::fillArc (const CRect &_rect, const CPoint &_point1, const CPoint &_point2)
+{
+ CRect rect (_rect);
+ rect.offset (offset.h, offset.v);
+ CPoint point1 (_point1);
+ point1.offset (offset.h, offset.v);
+ CPoint point2 (_point2);
+ point2.offset (offset.h, offset.v);
+
+ // Don't draw boundary
+ int angle1, angle2;
+ if ((point1.v == point2.v) && (point1.h == point2.h))
+ {
+ angle1 = 0;
+ angle2 = 23040; // 360 * 64
+ }
+ else
+ {
+ CPoint pm ((rect.left + rect.right) / 2, (rect.top + rect.bottom) / 2);
+ angle1 = convertPoint2Angle (pm, point1);
+ angle2 = convertPoint2Angle (pm, point2);
+ }
+
+ XFillArc (XDRAWPARAM, rect.left, rect.top, rect.width (), rect.height (),
+ angle1, angle2);
+}
+
+//-----------------------------------------------------------------------------
+void CDrawContext::setFontColor (const CColor color)
+{
+ fontColor = color;
+
+ setFrameColor (fontColor);
+}
+
+//-----------------------------------------------------------------------------
+void CDrawContext::setFrameColor (const CColor color)
+{
+ if (frameColor == color)
+ return;
+
+ frameColor = color;
+
+ XSetForeground (XGCPARAM, getIndexColor (frameColor));
+}
+
+//-----------------------------------------------------------------------------
+void CDrawContext::setFillColor (const CColor color)
+{
+ if (fillColor == color)
+ return;
+
+ fillColor = color;
+
+ // set the background for the text
+ //XSetBackground (XGCPARAM, getIndexColor (fillColor));
+ XSetBackground (display, pFrame->getGC(), getIndexColor (fillColor));
+
+ // set the foreground for the fill
+ setFrameColor (fillColor);
+}
+
+//-----------------------------------------------------------------------------
+void CDrawContext::setFont (CFont fontID, const long size, long style)
+{
+ if (fontID < 0 || fontID >= kNumStandardFonts)
+ fontID = kSystemFont;
+
+ if (fontId == fontID && fontSize == (size != 0 ? size : gStandardFontSize[fontID]) && fontStyle == style)
+ return;
+
+ fontStyle = style;
+ fontId = fontID;
+ if (size != 0)
+ fontSize = size;
+ else
+ fontSize = gStandardFontSize[fontID];
+
+ if (gFontStructs[fontID] != NULL)
+ XSetFont (display, pFrame->getGC(), gFontStructs[fontID]->fid);
+ else
+ fprintf(stderr, "ERROR: Font not defined\n");
+
+ // keep trace of the current font
+ pFontInfoStruct = gFontStructs[fontID];
+
+#ifdef DEBUG
+// if (!pFontInfoStruct) assert (false); // fonts have invalid pointers !
+#endif
+}
+
+//------------------------------------------------------------------------------
+CCoord CDrawContext::getStringWidth (const char *pStr)
+{
+ CCoord result = 0;
+
+ result = (long) XTextWidth (pFontInfoStruct, pStr, strlen (pStr));
+
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+void CDrawContext::drawString (const char *string, const CRect &_rect,
+ const short opaque, const CHoriTxtAlign hAlign)
+{
+ if (!string)
+ return;
+
+ CRect rect (_rect);
+ rect.offset (offset.h, offset.v);
+
+ int width;
+ int fontHeight = pFontInfoStruct->ascent + pFontInfoStruct->descent;
+ int xPos;
+ int yPos;
+ int rectHeight = rect.height ();
+
+ if (rectHeight >= fontHeight)
+ yPos = rect.bottom - (rectHeight - fontHeight) / 2;
+ else
+ yPos = rect.bottom;
+ yPos -= pFontInfoStruct->descent;
+
+ switch (hAlign)
+ {
+ case kCenterText:
+ width = XTextWidth (pFontInfoStruct, string, strlen (string));
+ xPos = (rect.right + rect.left - width) / 2;
+ break;
+
+ case kRightText:
+ width = XTextWidth (pFontInfoStruct, string, strlen (string));
+ xPos = rect.right - width;
+ break;
+
+ default: // left adjust
+ xPos = rect.left + 1;
+ }
+
+ if (opaque)
+ XDrawImageString (XDRAWPARAM, xPos, yPos, string, strlen (string));
+ else
+ XDrawString (XDRAWPARAM, xPos, yPos, string, strlen (string));
+}
+
+//-----------------------------------------------------------------------------
+long CDrawContext::getMouseButtons ()
+{
+ long buttons = 0;
+
+ Window root, child;
+ int rootX, rootY, childX, childY;
+ unsigned int mask;
+
+ XQueryPointer (XWINPARAM,
+ &root,
+ &child,
+ &rootX,
+ &rootY,
+ &childX,
+ &childY,
+ &mask);
+
+ if (mask & Button1Mask)
+ buttons |= kLButton;
+ if (mask & Button2Mask)
+ buttons |= kMButton;
+ if (mask & Button3Mask)
+ buttons |= kRButton;
+
+ if (mask & ShiftMask)
+ buttons |= kShift;
+ if (mask & ControlMask)
+ buttons |= kControl;
+ if (mask & Mod1Mask)
+ buttons |= kAlt;
+
+ return buttons;
+}
+
+//-----------------------------------------------------------------------------
+void CDrawContext::getMouseLocation (CPoint &point)
+{
+ Window root, child;
+ int rootX, rootY, childX, childY;
+ unsigned int mask;
+
+ XQueryPointer (XWINPARAM,
+ &root,
+ &child,
+ &rootX,
+ &rootY,
+ &childX,
+ &childY,
+ &mask);
+
+ point (childX, childY);
+
+ point.offset (-offsetScreen.h, -offsetScreen.v);
+}
+
+//-----------------------------------------------------------------------------
+bool CDrawContext::waitDoubleClick ()
+{
+ bool doubleClick = false;
+
+ long currentTime = _getTicks ();
+ long clickTime = currentTime + 200; // XtGetMultiClickTime (display);
+
+ XEvent e;
+ while (currentTime < clickTime)
+ {
+ if (XCheckTypedEvent (display, ButtonPress, &e))
+ {
+ doubleClick = true;
+ break;
+ }
+
+ currentTime = _getTicks ();
+ }
+
+ return doubleClick;
+}
+
+//-----------------------------------------------------------------------------
+bool CDrawContext::waitDrag ()
+{
+ if (!pFrame)
+ return false;
+
+ CPoint mouseLoc;
+ getMouseLocation (mouseLoc);
+ CRect observe (mouseLoc.h - 2, mouseLoc.v - 2, mouseLoc.h + 2, mouseLoc.v + 2);
+
+ long currentTime = pFrame->getTicks ();
+ bool wasOutside = false;
+
+ while (((getMouseButtons () & ~(kMButton|kRButton)) & kLButton) != 0)
+ {
+ pFrame->doIdleStuff ();
+ if (!wasOutside)
+ {
+ getMouseLocation (mouseLoc);
+ if (!observe.pointInside (mouseLoc))
+ {
+ if (kDragDelay <= 0)
+ return true;
+ wasOutside = true;
+ }
+ }
+
+ if (wasOutside && (pFrame->getTicks () - currentTime > kDragDelay))
+ return true;
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+void CDrawContext::forget ()
+{
+ CReferenceCounter::forget ();
+}
+
+//-----------------------------------------------------------------------------
+long CDrawContext::getIndexColor (CColor color)
+{
+ XColor xcol;
+ xcol.red = color.red << 8;
+ xcol.green = color.green << 8;
+ xcol.blue = color.blue << 8;
+ xcol.flags = (DoRed | DoGreen | DoBlue);
+ XAllocColor (display, XDefaultColormap (display, 0), &xcol);
+ return xcol.pixel;
+}
+
+//-----------------------------------------------------------------------------
+Colormap CDrawContext::getColormap ()
+{
+ if (pFrame)
+ return pFrame->getColormap ();
+ else
+ return None;
+}
+
+//-----------------------------------------------------------------------------
+Visual* CDrawContext::getVisual ()
+{
+ if (pFrame)
+ return pFrame->getVisual ();
+ else
+ return None;
+}
+
+//-----------------------------------------------------------------------------
+unsigned int CDrawContext::getDepth ()
+{
+ if (pFrame)
+ return pFrame->getDepth ();
+ else
+ return None;
+}
+
+
+//-----------------------------------------------------------------------------
+// COffscreenContext Implementation
+//-----------------------------------------------------------------------------
+COffscreenContext::COffscreenContext (CDrawContext *pContext, CBitmap *pBitmapBg, bool drawInBitmap)
+: CDrawContext (pContext->pFrame, NULL, NULL)
+, pBitmap (0)
+, pBitmapBg (pBitmapBg)
+, height (20)
+, width (20)
+{
+ std::cout << "COffscreenContext::COffscreenContext with bitmap" << std::endl;
+
+ if (pBitmapBg)
+ {
+ height = pBitmapBg->getHeight ();
+ width = pBitmapBg->getWidth ();
+
+ clipRect (0, 0, width, height);
+ }
+
+#if DEBUG
+ gNbCOffscreenContext++;
+ gBitmapAllocation += (long)height * (long)width;
+#endif
+
+ bDestroyPixmap = false;
+
+// Window root = RootWindow (display, DefaultScreen (display));
+
+ // if no bitmap handle => create one
+ if (! pWindow)
+ {
+ pWindow = (void*) XCreatePixmap (display, pFrame->getWindow(), width, height, pFrame->getDepth ());
+ bDestroyPixmap = true;
+ }
+
+ // set the current font
+ if (pSystemContext)
+ setFont (kNormalFont);
+
+ if (!drawInBitmap)
+ {
+ // draw bitmap to Offscreen
+ CRect r (0, 0, width, height);
+ if (pBitmapBg)
+ pBitmapBg->draw (this, r);
+ else
+ {
+ setFillColor (kBlackCColor);
+ fillRect (r);
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+COffscreenContext::COffscreenContext (CFrame *pFrame, long width, long height, const CColor backgroundColor)
+: CDrawContext (pFrame, NULL, NULL)
+, pBitmap (0)
+, pBitmapBg (0)
+, height (height)
+, width (width)
+, backgroundColor (backgroundColor)
+{
+ std::cout << "COffscreenContext::COffscreenContext without bitmap" << std::endl;
+
+ clipRect (0, 0, width, height);
+
+#if DEBUG
+ gNbCOffscreenContext++;
+ gBitmapAllocation += height * width;
+#endif
+
+ bDestroyPixmap = true;
+
+ pWindow = (void*) XCreatePixmap (display,
+ pFrame->getWindow(),
+ width,
+ height,
+ pFrame->getDepth ());
+
+/*
+ // clear the pixmap
+ XGCValues values;
+ values.foreground = getIndexColor (backgroundColor);
+ GC gc = XCreateGC (display, (Window)pWindow, GCForeground, &values);
+ XFillRectangle (display, (Window)pWindow, gc, 0, 0, width, height);
+ XFreeGC (display, gc);
+*/
+
+ XGCValues values;
+ values.foreground = getIndexColor (backgroundColor);
+ pSystemContext = XCreateGC (display, (Window)pWindow, GCForeground, &values);
+ XFillRectangle (display, (Window)pWindow, (GC) pSystemContext, 0, 0, width, height);
+
+ // set the current font
+ if (pSystemContext)
+ setFont (kNormalFont);
+}
+
+//-----------------------------------------------------------------------------
+COffscreenContext::~COffscreenContext ()
+{
+#if DEBUG
+ gNbCOffscreenContext--;
+ gBitmapAllocation -= (long)height * (long)width;
+#endif
+
+ if (pBitmap)
+ pBitmap->forget ();
+
+ if (bDestroyPixmap && pWindow)
+ XFreePixmap (display, (Pixmap)pWindow);
+
+ if (pSystemContext)
+ XFreeGC (display, (GC) pSystemContext);
+}
+
+//-----------------------------------------------------------------------------
+void COffscreenContext::copyTo (CDrawContext* pContext, CRect& srcRect, CPoint destOffset)
+{
+ std::cout << "COffscreenContext::copyTo" << std::endl;
+
+ XCopyArea (display,
+ (Drawable) pContext->pWindow,
+ (Drawable) pWindow,
+ (GC) pSystemContext,
+ srcRect.left,
+ srcRect.top,
+ srcRect.width (),
+ srcRect.height (),
+ destOffset.h,
+ destOffset.v);
+}
+
+//-----------------------------------------------------------------------------
+void COffscreenContext::copyFrom (CDrawContext *pContext, CRect destRect, CPoint srcOffset)
+{
+ //std::cout << "COffscreenContext::copyFrom ";
+
+ XCopyArea (display,
+ (Drawable) pContext->pWindow,
+ (Drawable) pWindow,
+ (GC) pSystemContext,
+ srcOffset.h,
+ srcOffset.v,
+ destRect.width(),
+ destRect.height(),
+ destRect.left,
+ destRect.top);
+
+ pContext->setFrameColor (kRedCColor);
+ pContext->drawRect (destRect);
+}
+
+
+//-----------------------------------------------------------------------------
+class CAttributeListEntry
+{
+public:
+ CAttributeListEntry (long size, CViewAttributeID id)
+ : nextEntry (0)
+ , pointer (0)
+ , sizeOfPointer (size)
+ , id (id)
+ {
+ pointer = malloc (size);
+ }
+
+ ~CAttributeListEntry ()
+ {
+ if (pointer)
+ free (pointer);
+ }
+
+ CViewAttributeID getID () const { return id; }
+ long getSize () const { return sizeOfPointer; }
+ void* getPointer () const { return pointer; }
+ CAttributeListEntry* getNext () const { return nextEntry; }
+
+ void setNext (CAttributeListEntry* entry) { nextEntry = entry; }
+
+protected:
+ CAttributeListEntry () : nextEntry (0), pointer (0), sizeOfPointer (0), id (0) {}
+
+ CAttributeListEntry* nextEntry;
+ void* pointer;
+ long sizeOfPointer;
+ CViewAttributeID id;
+};
+
+//-----------------------------------------------------------------------------
+const char* kMsgCheckIfViewContainer = "kMsgCheckIfViewContainer";
+
+//-----------------------------------------------------------------------------
+// CView
+//-----------------------------------------------------------------------------
+/*! @class CView
+base class of all view objects
+*/
+//-----------------------------------------------------------------------------
+CView::CView (const CRect& size)
+: size (size)
+, mouseableArea (size)
+, pParentFrame (0)
+, pParentView (0)
+, bDirty (false)
+, bMouseEnabled (true)
+, bTransparencyEnabled (false)
+, bWantsFocus (false)
+, bVisible (true)
+, pBackground (0)
+, pAttributeList (0)
+{
+#if DEBUG
+ gNbCView++;
+#endif
+}
+
+//-----------------------------------------------------------------------------
+CView::~CView ()
+{
+ if (pBackground)
+ pBackground->forget ();
+
+ if (pAttributeList)
+ {
+ CAttributeListEntry* entry = pAttributeList;
+ while (entry)
+ {
+ CAttributeListEntry* nextEntry = entry->getNext ();
+ delete entry;
+ entry = nextEntry;
+ }
+ }
+#if DEBUG
+ gNbCView--;
+#endif
+}
+
+//-----------------------------------------------------------------------------
+void CView::getMouseLocation (CDrawContext* context, CPoint &point)
+{
+ if (context)
+ {
+ if (pParentView && pParentView->notify (this, kMsgCheckIfViewContainer) == kMessageNotified)
+ {
+ CCoord save[4];
+ ((CViewContainer*)pParentView)->modifyDrawContext (save, context);
+ pParentView->getMouseLocation (context, point);
+ ((CViewContainer*)pParentView)->restoreDrawContext (context, save);
+ }
+ else
+ context->getMouseLocation (point);
+ }
+}
+
+//-----------------------------------------------------------------------------
+CPoint& CView::frameToLocal (CPoint& point) const
+{
+ if (pParentView && pParentView->isTypeOf ("CViewContainer"))
+ return pParentView->frameToLocal (point);
+ return point;
+}
+
+//-----------------------------------------------------------------------------
+CPoint& CView::localToFrame (CPoint& point) const
+{
+ if (pParentView && pParentView->isTypeOf ("CViewContainer"))
+ return pParentView->localToFrame (point);
+ return point;
+}
+
+//-----------------------------------------------------------------------------
+void CView::redraw ()
+{
+ if (pParentFrame)
+ pParentFrame->draw (this);
+}
+
+//-----------------------------------------------------------------------------
+void CView::redrawRect (CDrawContext* context, const CRect& rect)
+{
+ if (pParentView)
+ pParentView->redrawRect (context, rect);
+ else if (pParentFrame)
+ pParentFrame->drawRect (context, rect);
+}
+
+//-----------------------------------------------------------------------------
+void CView::draw (CDrawContext *pContext)
+{
+ if (pBackground)
+ {
+ if (bTransparencyEnabled)
+ pBackground->drawTransparent (pContext, size);
+ else
+ pBackground->draw (pContext, size);
+ }
+ setDirty (false);
+}
+
+//-----------------------------------------------------------------------------
+void CView::mouse (CDrawContext *pContext, CPoint &where, long buttons)
+{}
+
+//-----------------------------------------------------------------------------
+bool CView::onWheel (CDrawContext *pContext, const CPoint &where, float distance)
+{
+ return false;
+}
+
+//------------------------------------------------------------------------
+bool CView::onWheel (CDrawContext *pContext, const CPoint &where, const CMouseWheelAxis axis, float distance)
+{
+ return onWheel (pContext, where, distance);
+}
+
+//------------------------------------------------------------------------
+void CView::update (CDrawContext *pContext)
+{
+ if (isDirty ())
+ {
+#if NEW_UPDATE_MECHANISM
+ if (pContext)
+ redrawRect (pContext, size);
+ else
+ redraw ();
+#else
+ #if USE_ALPHA_BLEND
+ if (pContext)
+ {
+ if (bTransparencyEnabled)
+ getFrame ()->drawRect (pContext, size);
+ else
+ draw (pContext);
+ }
+ #else
+ if (pContext)
+ draw (pContext);
+ #endif
+ else
+ redraw ();
+#endif
+ setDirty (false);
+ }
+}
+
+//------------------------------------------------------------------------------
+long CView::onKeyDown (VstKeyCode& keyCode)
+{
+ return -1;
+}
+
+//------------------------------------------------------------------------------
+long CView::onKeyUp (VstKeyCode& keyCode)
+{
+ return -1;
+}
+
+//------------------------------------------------------------------------------
+long CView::notify (CView* sender, const char* message)
+{
+ return kMessageUnknown;
+}
+
+//------------------------------------------------------------------------------
+void CView::looseFocus (CDrawContext *pContext)
+{}
+
+//------------------------------------------------------------------------------
+void CView::takeFocus (CDrawContext *pContext)
+{}
+
+//------------------------------------------------------------------------------
+void CView::setViewSize (CRect &rect)
+{
+ size = rect;
+ setDirty ();
+}
+
+//-----------------------------------------------------------------------------
+void *CView::getEditor () const
+{
+ return pParentFrame ? pParentFrame->getEditor () : 0;
+}
+
+//-----------------------------------------------------------------------------
+void CView::setBackground (CBitmap *background)
+{
+ if (pBackground)
+ pBackground->forget ();
+ pBackground = background;
+ if (pBackground)
+ pBackground->remember ();
+ setDirty (true);
+}
+
+//-----------------------------------------------------------------------------
+const CViewAttributeID kCViewAttributeReferencePointer = (CViewAttributeID) "cvrp";
+
+//-----------------------------------------------------------------------------
+/**
+ * @param id the ID of the Attribute
+ * @param outSize on return the size of the attribute
+ */
+bool CView::getAttributeSize (const CViewAttributeID id, long& outSize) const
+{
+ if (pAttributeList)
+ {
+ CAttributeListEntry* entry = pAttributeList;
+ while (entry)
+ {
+ if (entry->getID () == id)
+ break;
+ entry = entry->getNext ();
+ }
+ if (entry)
+ {
+ outSize = entry->getSize ();
+ return true;
+ }
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+/**
+ * @param id the ID of the Attribute
+ * @param inSize the size of the outData pointer
+ * @param outData a pointer where to copy the attribute data
+ * @param outSize the size in bytes which was copied into outData
+ */
+bool CView::getAttribute (const CViewAttributeID id, const long inSize, void* outData, long& outSize) const
+{
+ if (pAttributeList)
+ {
+ CAttributeListEntry* entry = pAttributeList;
+ while (entry)
+ {
+ if (entry->getID () == id)
+ break;
+ entry = entry->getNext ();
+ }
+ if (entry && inSize >= entry->getSize ())
+ {
+ outSize = entry->getSize ();
+ memcpy (outData, entry->getPointer (), outSize);
+ return true;
+ }
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+/**
+ * copies data into the attribute. If it does not exist, creates a new attribute.
+ * @param id the ID of the Attribute
+ * @param inSize the size of the outData pointer
+ * @param inData a pointer to the data
+ */
+bool CView::setAttribute (const CViewAttributeID id, const long inSize, void* inData)
+{
+ CAttributeListEntry* lastEntry = 0;
+ if (pAttributeList)
+ {
+ CAttributeListEntry* entry = pAttributeList;
+ while (entry)
+ {
+ if (entry->getID () == id)
+ break;
+ if (entry->getNext () == 0)
+ lastEntry = entry;
+ entry = entry->getNext ();
+ }
+ if (entry)
+ {
+ if (entry->getSize () >= inSize)
+ {
+ memcpy (entry->getPointer (), inData, inSize);
+ return true;
+ }
+ else
+ return false;
+ }
+ }
+
+ // create a new attribute
+ CAttributeListEntry* newEntry = new CAttributeListEntry (inSize, id);
+ memcpy (newEntry->getPointer (), inData, inSize);
+ if (lastEntry)
+ lastEntry->setNext (newEntry);
+ else if (!pAttributeList)
+ pAttributeList = newEntry;
+ else
+ {
+ delete newEntry;
+ return false;
+ }
+ return true;
+}
+
+#if DEBUG
+//-----------------------------------------------------------------------------
+void CView::dumpInfo ()
+{
+ CRect viewRect = getViewSize (viewRect);
+ DebugPrint ("left:%4d, top:%4d, width:%4d, height:%4d ", viewRect.left, viewRect.top, viewRect.getWidth (), viewRect.getHeight ());
+ if (getMouseEnabled ())
+ DebugPrint ("(Mouse Enabled) ");
+ if (getTransparency ())
+ DebugPrint ("(Transparent) ");
+ CRect mouseRect = getMouseableArea (mouseRect);
+ if (mouseRect != viewRect)
+ DebugPrint (" (Mouseable Area: left:%4d, top:%4d, width:%4d, height:%4d ", mouseRect.left, mouseRect.top, mouseRect.getWidth (), mouseRect.getHeight ());
+}
+#endif
+
+#define FOREACHSUBVIEW for (CCView *pSv = pFirstView; pSv; pSv = pSv->pNext) {CView *pV = pSv->pView;
+#define FOREACHSUBVIEW_REVERSE(reverse) for (CCView *pSv = reverse ? pLastView : pFirstView; pSv; pSv = reverse ? pSv->pPrevious : pSv->pNext) {CView *pV = pSv->pView;
+#define ENDFOR }
+
+//-----------------------------------------------------------------------------
+// CFrame Implementation
+//-----------------------------------------------------------------------------
+/*! @class CFrame
+It creates a platform dependend view object.
+On classic Mac OS it just draws into the provided window.
+On Mac OS X it is a ControlRef.
+On Windows it's a WS_CHILD Window.
+*/
+CFrame::CFrame (const CRect &inSize, void *inSystemWindow, void *inEditor)
+: CViewContainer (inSize, 0, 0)
+, pEditor (inEditor)
+, pModalView (0)
+, pFocusView (0)
+, bFirstDraw (true)
+, bDropActive (false)
+, bUpdatesDisabled (false)
+, pSystemWindow ((Window)inSystemWindow)
+, pFrameContext (0)
+, bAddedWindow (false)
+, defaultCursor (0)
+{
+ setOpenFlag (true);
+
+ pParentFrame = this;
+
+ depth = 0;
+ pVisual = 0;
+ window = 0;
+ gc = 0;
+
+ if (display == NULL)
+ display = XOpenDisplay(NULL);
+
+ initFrame ((void*)pSystemWindow);
+ backBuffer = XdbeAllocateBackBufferName(display, (Window)window, XdbeUndefined);
+
+ XGCValues values;
+ values.foreground = 1;
+ gc = XCreateGC (display, (Window)backBuffer, GCForeground, &values);
+
+ pFrameContext = new CDrawContext (this, gc, (void*)backBuffer);
+}
+
+//-----------------------------------------------------------------------------
+CFrame::~CFrame ()
+{
+ if (pModalView)
+ removeView (pModalView, false);
+
+ setCursor (kCursorDefault);
+
+ setDropActive (false);
+
+ if (pFrameContext)
+ pFrameContext->forget ();
+
+ if (getOpenFlag ())
+ close ();
+
+ if (window)
+ XDestroyWindow (display, (Window) window);
+ window = 0;
+
+ // remove callbacks to avoid undesirable update
+ if (gc)
+ freeGc ();
+}
+
+//-----------------------------------------------------------------------------
+bool CFrame::open ()
+{
+ if (! window)
+ return false;
+
+ XMapRaised (display, window);
+
+ return getOpenFlag ();
+}
+
+//-----------------------------------------------------------------------------
+bool CFrame::close ()
+{
+ if (!window || !getOpenFlag () || !pSystemWindow)
+ return false;
+
+ XUnmapWindow (display, window);
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+bool xerror;
+int errorHandler (Display *dp, XErrorEvent *e)
+{
+ xerror = true;
+ return 0;
+}
+int getProperty (Window handle, Atom atom)
+{
+ int result = 0, userSize;
+ unsigned long bytes, userCount;
+ unsigned char *data;
+ Atom userType;
+ xerror = false;
+ XErrorHandler olderrorhandler = XSetErrorHandler (errorHandler);
+ XGetWindowProperty (display, handle, atom, 0, 1, false, AnyPropertyType,
+ &userType, &userSize, &userCount, &bytes, &data);
+ if (xerror == false && userCount == 1)
+ result = *(int*)data;
+ XSetErrorHandler (olderrorhandler);
+ return result;
+}
+
+void eventProc (XEvent* ev)
+{
+ CFrame* frame = (CFrame*) getProperty (ev->xany.window, XInternAtom (display, "_this", false));
+ if (frame == 0)
+ return;
+
+ switch (ev->type)
+ {
+ case ButtonPress:
+ {
+ CPoint where (ev->xbutton.x, ev->xbutton.y);
+ frame->mouse (frame->createDrawContext(), where);
+ break;
+ }
+
+ case MotionNotify:
+ {
+ CPoint where (ev->xbutton.x, ev->xbutton.y);
+ frame->mouse (frame->createDrawContext(), where);
+ break;
+ }
+
+ case ButtonRelease:
+ {
+ break;
+ }
+
+ case Expose:
+ {
+ CRect rc (ev->xexpose.x, ev->xexpose.y,
+ ev->xexpose.x + ev->xexpose.width, ev->xexpose.y + ev->xexpose.height);
+
+ while (XCheckTypedWindowEvent (display, ev->xexpose.window, Expose, ev))
+ {
+ rc.left = std::min ((int) rc.left, ev->xexpose.x);
+ rc.top = std::min ((int) rc.top, ev->xexpose.y);
+ rc.right = std::max ((int) rc.right, ev->xexpose.x + ev->xexpose.width);
+ rc.bottom = std::max ((int) rc.bottom, ev->xexpose.y + ev->xexpose.height);
+ }
+
+ frame->drawRect (0, rc);
+ break;
+ }
+
+ case EnterNotify:
+ break;
+
+ case LeaveNotify:
+ {
+ XCrossingEvent *xevent = (XCrossingEvent*) ev;
+ if (frame->getFocusView ())
+ {
+ if (xevent->x < 0 || xevent->x >= frame->getWidth ()
+ || xevent->y < 0 || xevent->y >= frame->getHeight ())
+ {
+ // if button pressed => don't defocus
+ if (xevent->state & (Button1Mask | Button2Mask | Button3Mask))
+ break;
+
+ frame->getFocusView ()->looseFocus ();
+ frame->setFocusView (0);
+ }
+ }
+ break;
+ }
+
+ case ConfigureNotify:
+ {
+ frame->draw (); // @XXX - keep out ?
+ break;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+bool CFrame::initFrame (void *systemWin)
+{
+ if (!systemWin)
+ return false;
+
+ // window attributes
+ XSetWindowAttributes swa;
+ swa.override_redirect = false;
+ swa.background_pixmap = None;
+ swa.colormap = 0;
+ swa.event_mask =
+ StructureNotifyMask | ExposureMask | KeyPressMask | KeyReleaseMask |
+ ButtonPressMask | ButtonReleaseMask | FocusChangeMask | PointerMotionMask |
+ EnterWindowMask | LeaveWindowMask | PropertyChangeMask;
+
+ // create child window of host supplied window
+ window = XCreateWindow (display, (Window)systemWin,
+ 0, 0, size.width(), size.height(),
+ 0, CopyFromParent, InputOutput, (Visual*) CopyFromParent,
+ CWEventMask | CWOverrideRedirect | CWColormap | CWBackPixmap | CWEventMask, &swa);
+
+ XGrabButton (display, AnyButton, AnyModifier, window, False,
+ ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask,
+ GrabModeAsync, GrabModeAsync, None, None);
+
+#if 0
+ // remove window caption/frame
+ #define MWM_HINTS_DECORATIONS (1L << 1)
+ #define PROP_MOTIF_WM_HINTS_ELEMENTS 5
+ typedef struct
+ {
+ unsigned long flags;
+ unsigned long functions;
+ unsigned long decorations;
+ long inputMode;
+ unsigned long status;
+ }
+ PropMotifWmHints;
+
+ PropMotifWmHints motif_hints;
+ motif_hints.flags = MWM_HINTS_DECORATIONS;
+ motif_hints.decorations = 0;
+ Atom prop = XInternAtom (display, "_MOTIF_WM_HINTS", True );
+ XChangeProperty (display, window, prop, prop, 32, PropModeReplace,
+ (unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
+#endif
+
+ Atom atom;
+ void* data = this;
+ atom = XInternAtom (display, "_this", false);
+ XChangeProperty (display, (Window)window, atom, atom, 32,
+ PropModeReplace, (unsigned char*)&data, 1);
+
+ data = (void*)&eventProc;
+ atom = XInternAtom (display, "_XEventProc", false);
+ XChangeProperty (display, (Window)window, atom, atom, 32,
+ PropModeReplace, (unsigned char*)&data, 1);
+
+ XGCValues values;
+ values.foreground = 1;
+ gc = XCreateGC (display, (Window)window, GCForeground, &values);
+
+ // get the std colormap
+ XWindowAttributes attr;
+ XGetWindowAttributes (display, (Window) window, &attr);
+ colormap = attr.colormap;
+ pVisual = attr.visual;
+ depth = attr.depth;
+
+ // init and load the fonts
+ if (! gFontInit) {
+ for (long i = 0; i < kNumStandardFonts; i++) {
+ DBG (gFontTable[i].string);
+ gFontStructs[i] = XLoadQueryFont (display, gFontTable[i].string);
+ assert (gFontStructs[i] != 0);
+ }
+ gFontInit = true;
+ }
+
+ setDropActive (true);
+ bAddedWindow = true;
+
+ //XReparentWindow (display, window, (Window) systemWin, 0, 0);
+ //XMapRaised (display, window);
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+bool CFrame::setDropActive (bool val)
+{
+ if (!bDropActive && !val)
+ return true;
+
+ bDropActive = val;
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+void CFrame::freeGc ()
+{
+ XFreeGC (display, gc);
+}
+
+//-----------------------------------------------------------------------------
+CDrawContext* CFrame::createDrawContext ()
+{
+ if (pFrameContext)
+ {
+ pFrameContext->remember ();
+ return pFrameContext;
+ }
+
+ pFrameContext = new CDrawContext (this, gc, (void*)window);
+
+ return pFrameContext;
+}
+
+//-----------------------------------------------------------------------------
+void CFrame::draw (CDrawContext *pContext)
+{
+ if (bFirstDraw)
+ bFirstDraw = false;
+
+ bool localContext = false;
+ if (! pContext)
+ {
+ localContext = true;
+ pContext = createDrawContext ();
+ }
+
+ // draw the background and the children
+ CViewContainer::draw (pContext);
+
+ if (localContext)
+ pContext->forget ();
+}
+
+//-----------------------------------------------------------------------------
+void CFrame::drawRect (CDrawContext *pContext, const CRect& updateRect)
+{
+ if (bFirstDraw)
+ bFirstDraw = false;
+
+ bool localContext = false;
+ if (! pContext)
+ {
+ localContext = true;
+ pContext = createDrawContext ();
+ }
+
+#if USE_CLIPPING_DRAWRECT
+ CRect oldClip;
+ pContext->getClipRect (oldClip);
+ CRect newClip (updateRect);
+ newClip.bound (oldClip);
+ pContext->setClipRect (newClip);
+#endif
+
+ // draw the background and the children
+ if (updateRect.getWidth () > 0 && updateRect.getHeight () > 0)
+ CViewContainer::drawRect (pContext, updateRect);
+
+#if USE_CLIPPING_DRAWRECT
+ pContext->setClipRect (oldClip);
+#endif
+
+ if (localContext)
+ pContext->forget ();
+}
+
+//-----------------------------------------------------------------------------
+void CFrame::draw (CView *pView)
+{
+ CView *pViewToDraw = 0;
+
+ // Search it in the view list
+ if (pView && isChild(pView))
+ pViewToDraw = pView;
+
+ CDrawContext *pContext = createDrawContext ();
+ if (pContext)
+ {
+ if (pViewToDraw && pViewToDraw->isVisible())
+ pViewToDraw->draw (pContext);
+ else
+ draw (pContext);
+
+ pContext->forget ();
+ }
+}
+
+//-----------------------------------------------------------------------------
+void CFrame::mouse (CDrawContext *pContext, CPoint &where, long buttons)
+{
+/*
+ XGrabPointer (display,
+ window,
+ False,
+ ButtonPressMask | ButtonReleaseMask |
+ EnterWindowMask | LeaveWindowMask |
+ PointerMotionMask | Button1MotionMask |
+ Button2MotionMask | Button3MotionMask |
+ Button4MotionMask | Button5MotionMask,
+ GrabModeAsync,
+ GrabModeAsync,
+ None,
+ None,
+ CurrentTime);
+*/
+
+ if (!pContext)
+ pContext = pFrameContext;
+
+ if (pFocusView)
+ setFocusView (NULL);
+
+ if (buttons == -1 && pContext)
+ buttons = pContext->getMouseButtons ();
+
+ if (pModalView && pModalView->isVisible())
+ {
+ if (pModalView->hitTest (where, buttons))
+ pModalView->mouse (pContext, where, buttons);
+ }
+ else
+ {
+ CViewContainer::mouse (pContext, where, buttons);
+ }
+
+// XUngrabPointer (display, CurrentTime);
+}
+
+//-----------------------------------------------------------------------------
+long CFrame::onKeyDown (VstKeyCode& keyCode)
+{
+ long result = -1;
+
+ if (pFocusView && pFocusView->isVisible())
+ result = pFocusView->onKeyDown (keyCode);
+
+ if (result == -1 && pModalView && pModalView->isVisible())
+ result = pModalView->onKeyDown (keyCode);
+
+ if (result == -1 && keyCode.virt == VKEY_TAB)
+ result = advanceNextFocusView (pFocusView, (keyCode.modifier & MODIFIER_SHIFT) ? true : false) ? 1 : -1;
+
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+long CFrame::onKeyUp (VstKeyCode& keyCode)
+{
+ long result = -1;
+
+ if (pFocusView && pFocusView->isVisible())
+ result = pFocusView->onKeyUp (keyCode);
+
+ if (result == -1 && pModalView && pModalView->isVisible())
+ result = pModalView->onKeyUp (keyCode);
+
+ return result;
+}
+
+//------------------------------------------------------------------------
+bool CFrame::onWheel (CDrawContext *pContext, const CPoint &where, const CMouseWheelAxis axis, float distance)
+{
+ bool result = false;
+
+ CView *view = pModalView ? pModalView : getViewAt (where);
+ if (view && view->isVisible())
+ {
+ bool localContext = false;
+ if (!pContext)
+ {
+ localContext = true;
+ pContext = createDrawContext ();
+ }
+
+ result = view->onWheel (pContext, where, axis, distance);
+
+ if (localContext)
+ pContext->forget ();
+ }
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+bool CFrame::onWheel (CDrawContext *pContext, const CPoint &where, float distance)
+{
+ return onWheel (pContext, where, kMouseWheelAxisY, distance);
+}
+
+//-----------------------------------------------------------------------------
+void CFrame::update (CDrawContext *pContext)
+{
+ if (!getOpenFlag () || updatesDisabled ())
+ return;
+
+ CDrawContext* dc = pContext;
+
+ if (bDirty)
+ {
+ draw (dc);
+ setDirty (false);
+ }
+ else
+ {
+#if USE_CLIPPING_DRAWRECT
+ CRect oldClipRect;
+ dc->getClipRect (oldClipRect);
+#endif
+#if NEW_UPDATE_MECHANISM
+ if (pModalView && pModalView->isVisible () && pModalView->isDirty ())
+ pModalView->update (dc);
+#endif
+ FOREACHSUBVIEW
+#if USE_CLIPPING_DRAWRECT
+ CRect viewSize (pV->size);
+ viewSize.bound (oldClipRect);
+ dc->setClipRect (viewSize);
+#endif
+ pV->update (dc);
+ ENDFOR
+#if USE_CLIPPING_DRAWRECT
+ dc->setClipRect (oldClipRect);
+#endif
+ }
+}
+
+//-----------------------------------------------------------------------------
+void CFrame::idle ()
+{
+ if (!getOpenFlag ())
+ return;
+
+ // don't do an idle before a draw
+ if (bFirstDraw)
+ return;
+
+ if (!isDirty ())
+ return;
+
+ XdbeBeginIdiom(display);
+ XdbeSwapInfo swap_info;
+ swap_info.swap_window = window;
+ swap_info.swap_action = XdbeUndefined;
+ XdbeSwapBuffers(display, &swap_info, 1);
+
+ CDrawContext *pContext = createDrawContext ();
+
+ update (pContext);
+
+ pContext->forget ();
+
+ XdbeEndIdiom(display);
+}
+
+//-----------------------------------------------------------------------------
+void CFrame::doIdleStuff ()
+{
+ if (pEditor)
+ ((AEffGUIEditor*)pEditor)->doIdleStuff ();
+}
+
+//-----------------------------------------------------------------------------
+unsigned long CFrame::getTicks () const
+{
+ if (pEditor)
+ return ((AEffGUIEditor*)pEditor)->getTicks ();
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+long CFrame::getKnobMode () const
+{
+ return AEffGUIEditor::getKnobMode ();
+}
+
+//-----------------------------------------------------------------------------
+bool CFrame::setPosition (CCoord x, CCoord y)
+{
+ size.left = 0;
+ size.top = 0;
+
+ XWindowChanges attr;
+ attr.x = x;
+ attr.y = y;
+
+ XConfigureWindow (display, window, CWX | CWY, &attr);
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+bool CFrame::getPosition (CCoord &x, CCoord &y) const
+{
+ x = size.left;
+ y = size.top;
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+void CFrame::setViewSize (CRect& inRect)
+{
+ setSize (inRect.width (), inRect.height ());
+}
+
+//-----------------------------------------------------------------------------
+bool CFrame::setSize (CCoord width, CCoord height)
+{
+ if ((width == size.width ()) && (height == size.height ()))
+ return false;
+
+ // set the new size
+ size.right = size.left + width;
+ size.bottom = size.top + height;
+
+ XResizeWindow (display, window, size.width (), size.height ());
+
+ CRect myViewSize (0, 0, size.width (), size.height ());
+ CViewContainer::setViewSize (myViewSize);
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+bool CFrame::getSize (CRect *pRect) const
+{
+// if (!getOpenFlag ())
+// return false;
+
+ pRect->left = 0;
+ pRect->top = 0;
+ pRect->right = size.width () + pRect->left;
+ pRect->bottom = size.height () + pRect->top;
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+bool CFrame::getSize (CRect& outSize) const
+{
+ return getSize (&outSize);
+}
+
+//-----------------------------------------------------------------------------
+long CFrame::setModalView (CView *pView)
+{
+ // There's already a modal view so we get out
+ if (pView && pModalView)
+ return 0;
+
+ if (pModalView)
+ removeView (pModalView, false);
+
+ pModalView = pView;
+ if (pModalView)
+ addView (pModalView);
+
+ return 1;
+}
+
+//-----------------------------------------------------------------------------
+void CFrame::beginEdit (long index)
+{
+ if (pEditor)
+ ((AEffGUIEditor*)pEditor)->beginEdit (index);
+}
+
+//-----------------------------------------------------------------------------
+void CFrame::endEdit (long index)
+{
+ if (pEditor)
+ ((AEffGUIEditor*)pEditor)->endEdit (index);
+}
+
+//-----------------------------------------------------------------------------
+CView *CFrame::getCurrentView () const
+{
+ if (pModalView)
+ return pModalView;
+
+ return CViewContainer::getCurrentView ();
+}
+
+//-----------------------------------------------------------------------------
+bool CFrame::getCurrentLocation (CPoint &where)
+{
+ // create a local context
+ CDrawContext *pContext = createDrawContext ();
+ if (pContext)
+ {
+ // get the current position
+ pContext->getMouseLocation (where);
+ pContext->forget ();
+ }
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+void CFrame::setCursor (CCursorType type)
+{
+}
+
+//-----------------------------------------------------------------------------
+void CFrame::setFocusView (CView *pView)
+{
+ if (pView && ! pView->isVisible())
+ return;
+
+ CView *pOldFocusView = pFocusView;
+ pFocusView = pView;
+
+ if (pFocusView && pFocusView->wantsFocus ())
+ pFocusView->setDirty ();
+
+ if (pOldFocusView)
+ {
+ pOldFocusView->looseFocus ();
+ if (pOldFocusView->wantsFocus ())
+ pOldFocusView->setDirty ();
+ }
+}
+
+//-----------------------------------------------------------------------------
+bool CFrame::advanceNextFocusView (CView* oldFocus, bool reverse)
+{
+ if (pModalView)
+ return false; // currently not supported, but should be done sometime
+ if (oldFocus == 0)
+ {
+ if (pFocusView == 0)
+ return CViewContainer::advanceNextFocusView (0, reverse);
+ oldFocus = pFocusView;
+ }
+ if (isChild (oldFocus))
+ {
+ if (CViewContainer::advanceNextFocusView (oldFocus, reverse))
+ return true;
+ else
+ {
+ setFocusView (NULL);
+ return false;
+ }
+ }
+ CView* parentView = oldFocus->getParentView ();
+ if (parentView && parentView->isTypeOf ("CViewContainer"))
+ {
+ CView* tempOldFocus = oldFocus;
+ CViewContainer* vc = (CViewContainer*)parentView;
+ while (vc)
+ {
+ if (vc->advanceNextFocusView (tempOldFocus, reverse))
+ return true;
+ else
+ {
+ tempOldFocus = vc;
+ if (vc->getParentView () && vc->getParentView ()->isTypeOf ("CViewContainer"))
+ vc = (CViewContainer*)vc->getParentView ();
+ else
+ vc = 0;
+ }
+ }
+ }
+ return CViewContainer::advanceNextFocusView (oldFocus, reverse);
+}
+
+//-----------------------------------------------------------------------------
+void CFrame::invalidate (const CRect &rect)
+{
+ CRect rectView;
+ FOREACHSUBVIEW
+ if (pV)
+ {
+ pV->getViewSize (rectView);
+ if (rect.rectOverlap (rectView))
+ pV->setDirty (true);
+ }
+ ENDFOR
+
+ XClearArea (display,
+ window,
+ rect.left,
+ rect.top,
+ rect.right - rect.left,
+ rect.bottom - rect.top,
+ true);
+
+ XSync (display, false);
+
+/*
+ XEvent ev;
+ memset (&ev, 0, sizeof (XEvent));
+ ev.xexpose.type = Expose;
+ ev.xexpose.display = display;
+ ev.xexpose.window = (Window) window;
+
+ ev.xexpose.x = rect.left;
+ ev.xexpose.y = rect.top;
+ ev.xexpose.width = rect.right - rect.left;
+ ev.xexpose.height = rect.bottom - rect.top;
+
+ XSendEvent (display, (Window) window, False, 0L, &ev);
+ XFlush (display);
+*/
+}
+
+#if DEBUG
+//-----------------------------------------------------------------------------
+void CFrame::dumpHierarchy ()
+{
+ dumpInfo ();
+ DebugPrint ("\n");
+ CViewContainer::dumpHierarchy ();
+}
+#endif
+
+//-----------------------------------------------------------------------------
+// CCView Implementation
+//-----------------------------------------------------------------------------
+CCView::CCView (CView *pView)
+ : pView (pView), pNext (0), pPrevious (0)
+{
+ if (pView)
+ pView->remember ();
+}
+
+//-----------------------------------------------------------------------------
+CCView::~CCView ()
+{
+ if (pView)
+ pView->forget ();
+}
+
+//-----------------------------------------------------------------------------
+// CViewContainer Implementation
+//-----------------------------------------------------------------------------
+/**
+ * CViewContainer constructor.
+ * @param rect the size of the container
+ * @param pParent the parent CFrame
+ * @param pBackground the background bitmap, can be NULL
+ */
+CViewContainer::CViewContainer (const CRect &rect, CFrame *pParent, CBitmap *pBackground)
+ : CView (rect),
+ pFirstView (0),
+ pLastView (0),
+ mode (kNormalUpdate),
+ pOffscreenContext (0),
+ bDrawInOffscreen (false),
+ currentDragView (0)
+{
+ pParentFrame = pParent;
+
+ backgroundOffset (0, 0);
+
+ setBackground (pBackground);
+ backgroundColor = kBlackCColor;
+
+#if NEW_UPDATE_MECHANISM
+ mode = kOnlyDirtyUpdate;
+#endif
+}
+
+//-----------------------------------------------------------------------------
+CViewContainer::~CViewContainer ()
+{
+ // remove all views
+ removeAll (true);
+
+ if (pOffscreenContext)
+ pOffscreenContext->forget ();
+ pOffscreenContext = 0;
+}
+
+//-----------------------------------------------------------------------------
+/**
+ * @param rect the new size of the container
+ */
+void CViewContainer::setViewSize (CRect &rect)
+{
+ CView::setViewSize (rect);
+
+ if (pOffscreenContext && bDrawInOffscreen)
+ {
+ pOffscreenContext->forget ();
+ pOffscreenContext = new COffscreenContext (pParentFrame, (long)size.width (), (long)size.height (), kBlackCColor);
+ }
+}
+
+//-----------------------------------------------------------------------------
+/**
+ * @param color the new background color of the container
+ */
+void CViewContainer::setBackgroundColor (CColor color)
+{
+ backgroundColor = color;
+ setDirty (true);
+}
+
+//------------------------------------------------------------------------------
+long CViewContainer::notify (CView* sender, const char* message)
+{
+ if (message == kMsgCheckIfViewContainer)
+ return kMessageNotified;
+ return kMessageUnknown;
+}
+
+//-----------------------------------------------------------------------------
+/**
+ * @param pView the view object to add to this container
+ */
+void CViewContainer::addView (CView *pView)
+{
+ if (!pView)
+ return;
+
+ CCView *pSv = new CCView (pView);
+
+ pView->pParentFrame = pParentFrame;
+ pView->pParentView = this;
+
+ CCView *pV = pFirstView;
+ if (!pV)
+ {
+ pLastView = pFirstView = pSv;
+ }
+ else
+ {
+ while (pV->pNext)
+ pV = pV->pNext;
+ pV->pNext = pSv;
+ pSv->pPrevious = pV;
+ pLastView = pSv;
+ }
+ pView->attached (this);
+ pView->setDirty ();
+}
+
+//-----------------------------------------------------------------------------
+/**
+ * @param pView the view object to add to this container
+ * @param mouseableArea the view area in where the view will get mouse events
+ * @param mouseEnabled bool to set if view will get mouse events
+ */
+void CViewContainer::addView (CView *pView, CRect &mouseableArea, bool mouseEnabled)
+{
+ if (!pView)
+ return;
+
+ pView->setMouseEnabled (mouseEnabled);
+ pView->setMouseableArea (mouseableArea);
+
+ addView (pView);
+}
+
+//-----------------------------------------------------------------------------
+/**
+ * @param withForget bool to indicate if the view's reference counter should be decreased after removed from the container
+ */
+void CViewContainer::removeAll (const bool &withForget)
+{
+ CCView *pV = pFirstView;
+ while (pV)
+ {
+ CCView *pNext = pV->pNext;
+ if (pV->pView)
+ {
+ pV->pView->removed (this);
+ if (withForget)
+ pV->pView->forget ();
+ }
+
+ delete pV;
+
+ pV = pNext;
+ }
+ pFirstView = 0;
+ pLastView = 0;
+}
+
+//-----------------------------------------------------------------------------
+/**
+ * @param pView the view which should be removed from the container
+ * @param withForget bool to indicate if the view's reference counter should be decreased after removed from the container
+ */
+void CViewContainer::removeView (CView *pView, const bool &withForget)
+{
+ if (pParentFrame && pParentFrame->getFocusView () == pView)
+ pParentFrame->setFocusView (0);
+ CCView *pV = pFirstView;
+ while (pV)
+ {
+ if (pView == pV->pView)
+ {
+ CCView *pNext = pV->pNext;
+ CCView *pPrevious = pV->pPrevious;
+ if (pV->pView)
+ {
+ pV->pView->removed (this);
+ if (withForget)
+ pV->pView->forget ();
+ }
+ delete pV;
+ if (pPrevious)
+ {
+ pPrevious->pNext = pNext;
+ if (pNext)
+ pNext->pPrevious = pPrevious;
+ else
+ pLastView = pPrevious;
+ }
+ else
+ {
+ pFirstView = pNext;
+ if (pNext)
+ pNext->pPrevious = 0;
+ else
+ pLastView = 0;
+ }
+ break;
+ }
+ else
+ pV = pV->pNext;
+ }
+}
+
+//-----------------------------------------------------------------------------
+/**
+ * @param pView the view which should be checked if it is a child of this container
+ */
+bool CViewContainer::isChild (CView *pView) const
+{
+ bool found = false;
+
+ CCView *pV = pFirstView;
+ while (pV)
+ {
+ if (pView == pV->pView)
+ {
+ found = true;
+ break;
+ }
+ pV = pV->pNext;
+ }
+ return found;
+}
+
+//-----------------------------------------------------------------------------
+long CViewContainer::getNbViews () const
+{
+ long nb = 0;
+ CCView *pV = pFirstView;
+ while (pV)
+ {
+ pV = pV->pNext;
+ nb++;
+ }
+ return nb;
+}
+
+//-----------------------------------------------------------------------------
+/**
+ * @param index the index of the view to return
+ */
+CView *CViewContainer::getView (long index) const
+{
+ long nb = 0;
+ CCView *pV = pFirstView;
+ while (pV)
+ {
+ if (nb == index)
+ return pV->pView;
+ pV = pV->pNext;
+ nb++;
+ }
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+/**
+ * @param pContext the context which to use to draw this container and its subviews
+ */
+void CViewContainer::draw (CDrawContext *pContext)
+{
+ CDrawContext *pC;
+ CCoord save[4];
+
+ if (!pOffscreenContext && bDrawInOffscreen)
+ pOffscreenContext = new COffscreenContext (pParentFrame, (long)size.width (), (long)size.height (), kBlackCColor);
+
+#if USE_ALPHA_BLEND
+ if (pOffscreenContext && bTransparencyEnabled)
+ pOffscreenContext->copyTo (pContext, size);
+#endif
+
+ if (bDrawInOffscreen)
+ pC = pOffscreenContext;
+ else
+ {
+ pC = pContext;
+ modifyDrawContext (save, pContext);
+ }
+
+ CRect r (0, 0, size.width (), size.height ());
+
+#if USE_CLIPPING_DRAWRECT
+ CRect oldClip;
+ pContext->getClipRect (oldClip);
+ CRect oldClip2 (oldClip);
+ if (bDrawInOffscreen && getFrame () != this)
+ oldClip.offset (-oldClip.left, -oldClip.top);
+
+ CRect newClip (r);
+ newClip.bound (oldClip);
+ pC->setClipRect (newClip);
+#endif
+
+ // draw the background
+ if (pBackground)
+ {
+ if (bTransparencyEnabled)
+ pBackground->drawTransparent (pC, r, backgroundOffset);
+ else
+ pBackground->draw (pC, r, backgroundOffset);
+ }
+ else if (!bTransparencyEnabled)
+ {
+ pC->setFillColor (backgroundColor);
+ pC->fillRect (r);
+ }
+
+ // draw each view
+ FOREACHSUBVIEW
+#if USE_CLIPPING_DRAWRECT
+ CRect vSize (pV->size);
+ vSize.bound (oldClip);
+ pC->setClipRect (vSize);
+#endif
+ if (pV->isVisible())
+ pV->draw (pC);
+ ENDFOR
+
+#if USE_CLIPPING_DRAWRECT
+ pC->setClipRect (oldClip2);
+#endif
+
+ // transfert offscreen
+ if (bDrawInOffscreen)
+ ((COffscreenContext*)pC)->copyFrom (pContext, size);
+ else
+ restoreDrawContext (pContext, save);
+
+ setDirty (false);
+}
+
+//-----------------------------------------------------------------------------
+/**
+ * @param pContext the context which to use to draw the background
+ * @param _updateRect the area which to draw
+ */
+void CViewContainer::drawBackgroundRect (CDrawContext *pContext, CRect& _updateRect)
+{
+ if (pBackground)
+ {
+ CRect oldClip;
+ pContext->getClipRect (oldClip);
+ CRect newClip (_updateRect);
+ newClip.bound (oldClip);
+ pContext->setClipRect (newClip);
+ CRect tr (0, 0, pBackground->getWidth (), pBackground->getHeight ());
+ if (bTransparencyEnabled)
+ pBackground->drawTransparent (pContext, tr, backgroundOffset);
+ else
+ pBackground->draw (pContext, tr, backgroundOffset);
+ pContext->setClipRect (oldClip);
+ }
+ else if (!bTransparencyEnabled)
+ {
+ pContext->setFillColor (backgroundColor);
+ pContext->fillRect (_updateRect);
+ }
+}
+
+//-----------------------------------------------------------------------------
+/**
+ * @param pContext the context which to use to draw
+ * @param _updateRect the area which to draw
+ */
+void CViewContainer::drawRect (CDrawContext *pContext, const CRect& _updateRect)
+{
+ CDrawContext *pC;
+ CCoord save[4];
+
+ if (!pOffscreenContext && bDrawInOffscreen)
+ pOffscreenContext = new COffscreenContext (pParentFrame, (long)size.width (), (long)size.height (), kBlackCColor);
+
+#if USE_ALPHA_BLEND
+ if (pOffscreenContext && bTransparencyEnabled)
+ pOffscreenContext->copyTo (pContext, size);
+#endif
+
+ if (bDrawInOffscreen)
+ pC = pOffscreenContext;
+ else
+ {
+ pC = pContext;
+ modifyDrawContext (save, pContext);
+ }
+
+ CRect updateRect (_updateRect);
+ updateRect.bound (size);
+
+ CRect clientRect (updateRect);
+ clientRect.offset (-size.left, -size.top);
+
+#if USE_CLIPPING_DRAWRECT
+ CRect oldClip;
+ pContext->getClipRect (oldClip);
+ CRect oldClip2 (oldClip);
+ if (bDrawInOffscreen && getFrame () != this)
+ oldClip.offset (-oldClip.left, -oldClip.top);
+
+ CRect newClip (clientRect);
+ newClip.bound (oldClip);
+ pC->setClipRect (newClip);
+#endif
+
+ // draw the background
+ drawBackgroundRect (pC, clientRect);
+
+ // draw each view
+ FOREACHSUBVIEW
+ if (pV->isVisible() && pV->checkUpdate (clientRect))
+ {
+#if USE_CLIPPING_DRAWRECT
+ CRect viewSize (pV->size);
+ viewSize.bound (newClip);
+ if (viewSize.getWidth () == 0 || viewSize.getHeight () == 0)
+ continue;
+ pC->setClipRect (viewSize);
+#endif
+
+ bool wasDirty = pV->isDirty ();
+ pV->drawRect (pC, clientRect);
+
+#if DEBUG_FOCUS_DRAWING
+ if (getFrame ()->getFocusView() == pV && pV->wantsFocus ())
+ {
+ pC->setDrawMode (kCopyMode);
+ pC->setFrameColor (kRedCColor);
+ pC->drawRect (pV->size);
+ }
+#endif
+ if (wasDirty && /* pV->size != viewSize &&*/ !isTypeOf ("CScrollContainer"))
+ {
+ pV->setDirty (true);
+ }
+ }
+ ENDFOR
+
+#if USE_CLIPPING_DRAWRECT
+ pC->setClipRect (oldClip2);
+#endif
+
+ // transfer offscreen
+ if (bDrawInOffscreen)
+ ((COffscreenContext*)pC)->copyFrom (pContext, updateRect, CPoint (clientRect.left, clientRect.top));
+ else
+ restoreDrawContext (pContext, save);
+
+#if EVENT_DRAW_FIX
+ if (bDirty && newClip == size)
+#endif
+ setDirty (false);
+}
+
+//-----------------------------------------------------------------------------
+/**
+ * @param context the context which to use to redraw this container
+ * @param rect the area which to redraw
+ */
+void CViewContainer::redrawRect (CDrawContext* context, const CRect& rect)
+{
+ CRect _rect (rect);
+ _rect.offset (size.left, size.top);
+ if (bTransparencyEnabled)
+ {
+ // as this is transparent, we call the parentview to redraw this area.
+ if (pParentView)
+ pParentView->redrawRect (context, _rect);
+ else if (pParentFrame)
+ pParentFrame->drawRect (context, _rect);
+ }
+ else
+ {
+ CCoord save[4];
+ if (pParentView)
+ {
+ CPoint off;
+ pParentView->localToFrame (off);
+ // store
+ save[0] = context->offsetScreen.h;
+ save[1] = context->offsetScreen.v;
+ save[2] = context->offset.h;
+ save[3] = context->offset.v;
+
+ context->offsetScreen.h += off.x;
+ context->offsetScreen.v += off.y;
+ context->offset.h += off.x;
+ context->offset.v += off.y;
+
+ drawRect (context, _rect);
+
+ // restore
+ context->offsetScreen.h = save[0];
+ context->offsetScreen.v = save[1];
+ context->offset.h = save[2];
+ context->offset.v = save[3];
+ }
+ else
+ {
+ drawRect (context, _rect);
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+bool CViewContainer::hitTestSubViews (const CPoint& where, const long buttons)
+{
+ CPoint where2 (where);
+ where2.offset (-size.left, -size.top);
+
+ CCView *pSv = pLastView;
+ while (pSv)
+ {
+ CView *pV = pSv->pView;
+ if (pV && pV->getMouseEnabled () && pV->hitTest (where2, buttons))
+ return true;
+ pSv = pSv->pPrevious;
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+bool CViewContainer::hitTest (const CPoint& where, const long buttons)
+{
+ //return hitTestSubViews (where); would change default behavior
+ return CView::hitTest (where, buttons);
+}
+
+//-----------------------------------------------------------------------------
+void CViewContainer::mouse (CDrawContext *pContext, CPoint &where, long buttons)
+{
+ // convert to relativ pos
+ CPoint where2 (where);
+ where2.offset (-size.left, -size.top);
+
+ if (buttons == -1 && pContext)
+ buttons = pContext->getMouseButtons ();
+
+ CCView *pSv = pLastView;
+ while (pSv)
+ {
+ CView *pV = pSv->pView;
+ if (pV && pV->getMouseEnabled () && pV->hitTest (where2, buttons))
+ {
+ pV->mouse (pContext, where2, buttons);
+ break;
+ }
+ pSv = pSv->pPrevious;
+ }
+}
+
+//-----------------------------------------------------------------------------
+long CViewContainer::onKeyDown (VstKeyCode& keyCode)
+{
+ long result = -1;
+
+ CCView* pSv = pLastView;
+ while (pSv)
+ {
+ long result = pSv->pView->onKeyDown (keyCode);
+ if (result != -1)
+ break;
+
+ pSv = pSv->pPrevious;
+ }
+
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+long CViewContainer::onKeyUp (VstKeyCode& keyCode)
+{
+ long result = -1;
+
+ CCView* pSv = pLastView;
+ while (pSv)
+ {
+ long result = pSv->pView->onKeyUp (keyCode);
+ if (result != -1)
+ break;
+
+ pSv = pSv->pPrevious;
+ }
+
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+bool CViewContainer::onWheel (CDrawContext *pContext, const CPoint &where, const CMouseWheelAxis axis, float distance)
+{
+ bool result = false;
+ CView *view = getViewAt (where);
+ if (view)
+ {
+ // convert to relativ pos
+ CPoint where2 (where);
+ where2.offset (-size.left, -size.top);
+
+ CCoord save[4];
+ modifyDrawContext (save, pContext);
+
+ result = view->onWheel (pContext, where2, axis, distance);
+
+ restoreDrawContext (pContext, save);
+ }
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+bool CViewContainer::onWheel (CDrawContext *pContext, const CPoint &where, float distance)
+{
+ return onWheel (pContext, where, kMouseWheelAxisY, distance);
+}
+
+//-----------------------------------------------------------------------------
+bool CViewContainer::onDrop (CDrawContext* context, CDragContainer* drag, const CPoint& where)
+{
+ if (!pParentFrame)
+ return false;
+
+ bool result = false;
+
+ CCoord save[4];
+ modifyDrawContext (save, context);
+
+ // convert to relativ pos
+ CPoint where2 (where);
+ where2.offset (-size.left, -size.top);
+
+ CView* view = getViewAt (where);
+ if (view != currentDragView)
+ {
+ if (currentDragView)
+ currentDragView->onDragLeave (context, drag, where2);
+ currentDragView = view;
+ }
+ if (currentDragView)
+ {
+ result = currentDragView->onDrop (context, drag, where2);
+ currentDragView->onDragLeave (context, drag, where2);
+ }
+ currentDragView = 0;
+
+ restoreDrawContext (context, save);
+
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+void CViewContainer::onDragEnter (CDrawContext* context, CDragContainer* drag, const CPoint& where)
+{
+ if (!pParentFrame)
+ return;
+
+ CCoord save[4];
+ modifyDrawContext (save, context);
+
+ // convert to relativ pos
+ CPoint where2 (where);
+ where2.offset (-size.left, -size.top);
+
+ if (currentDragView)
+ currentDragView->onDragLeave (context, drag, where2);
+ CView* view = getViewAt (where);
+ currentDragView = view;
+ if (view)
+ view->onDragEnter (context, drag, where2);
+
+ restoreDrawContext (context, save);
+}
+
+//-----------------------------------------------------------------------------
+void CViewContainer::onDragLeave (CDrawContext* context, CDragContainer* drag, const CPoint& where)
+{
+ if (!pParentFrame)
+ return;
+
+ CCoord save[4];
+ modifyDrawContext (save, context);
+
+ // convert to relativ pos
+ CPoint where2 (where);
+ where2.offset (-size.left, -size.top);
+
+ if (currentDragView)
+ currentDragView->onDragLeave (context, drag, where2);
+ currentDragView = 0;
+
+ restoreDrawContext (context, save);
+}
+
+//-----------------------------------------------------------------------------
+void CViewContainer::onDragMove (CDrawContext* context, CDragContainer* drag, const CPoint& where)
+{
+ if (!pParentFrame)
+ return;
+
+ CCoord save[4];
+ modifyDrawContext (save, context);
+
+ // convert to relativ pos
+ CPoint where2 (where);
+ where2.offset (-size.left, -size.top);
+
+ CView* view = getViewAt (where);
+ if (view != currentDragView)
+ {
+ if (currentDragView)
+ currentDragView->onDragLeave (context, drag, where2);
+ if (view)
+ view->onDragEnter (context, drag, where2);
+ currentDragView = view;
+ }
+ else if (currentDragView)
+ currentDragView->onDragMove (context, drag, where2);
+
+ restoreDrawContext (context, save);
+}
+
+//-----------------------------------------------------------------------------
+void CViewContainer::update (CDrawContext *pContext)
+{
+ switch (mode)
+ {
+ //---Normal : redraw all...
+ case kNormalUpdate:
+ if (isDirty ())
+ {
+#if NEW_UPDATE_MECHANISM
+ CRect ur (0, 0, size.width (), size.height ());
+ redrawRect (pContext, ur);
+#else
+ #if USE_ALPHA_BLEND
+ if (bTransparencyEnabled)
+ {
+ CRect updateRect (size);
+ CPoint offset (0,0);
+ localToFrame (offset);
+ updateRect.offset (offset.x, offset.y);
+ getFrame ()->drawRect (pContext, updateRect);
+ }
+ else
+ #endif
+ draw (pContext);
+ #endif
+ setDirty (false);
+ }
+ break;
+
+ //---Redraw only dirty controls-----
+ case kOnlyDirtyUpdate:
+ {
+#if NEW_UPDATE_MECHANISM
+ if (bDirty)
+ {
+ CRect ur (0, 0, size.width (), size.height ());
+ redrawRect (pContext, ur);
+ }
+ else
+ {
+ CRect updateRect (size);
+ updateRect.offset (-size.left, -size.top);
+ FOREACHSUBVIEW
+ if (pV->isDirty () && pV->checkUpdate (updateRect))
+ {
+ if (pV->notify (this, kMsgCheckIfViewContainer))
+ pV->update (pContext);
+ else
+ {
+ CRect drawSize (pV->size);
+ drawSize.bound (updateRect);
+ pV->redrawRect (pContext, drawSize);
+ }
+ }
+ ENDFOR
+ }
+#else
+ #if USE_ALPHA_BLEND
+ if (bTransparencyEnabled)
+ {
+ if (bDirty)
+ {
+ CRect updateRect (size);
+ CPoint offset (0,0);
+ localToFrame (offset);
+ updateRect.offset (offset.x, offset.y);
+ getFrame ()->drawRect (pContext, updateRect);
+ }
+ else
+ {
+ CRect updateRect (size);
+ updateRect.offset (-size.left, -size.top);
+ FOREACHSUBVIEW
+ if (pV->isDirty () && pV->checkUpdate (updateRect))
+ {
+ if (pV->notify (this, kMsgCheckIfViewContainer))
+ {
+ pV->update (pContext);
+ }
+ else
+ {
+ CPoint offset;
+ CRect viewSize (pV->size);
+ pV->localToFrame (offset);
+ viewSize.offset (offset.x, offset.y);
+ getFrame ()->drawRect (pContext, viewSize);
+ }
+ }
+ ENDFOR
+ }
+ setDirty (false);
+ return;
+ }
+ #endif
+ if (bDirty)
+ draw (pContext);
+ else if (bDrawInOffscreen && pOffscreenContext)
+ {
+ bool doCopy = false;
+ if (isDirty ())
+ doCopy = true;
+
+ FOREACHSUBVIEW
+ pV->update (pOffscreenContext);
+ ENDFOR
+
+ // transfert offscreen
+ if (doCopy)
+ pOffscreenContext->copyFrom (pContext, size);
+ }
+ else
+ {
+ long save[4];
+ modifyDrawContext (save, pContext);
+
+ FOREACHSUBVIEW
+ if (pV->isDirty ())
+ {
+ long oldMode = 0;
+ CViewContainer* child = 0;
+ if (pV->notify (this, kMsgCheckIfViewContainer))
+ {
+ child = (CViewContainer*)pV;
+ oldMode = child->getMode ();
+ child->setMode (kNormalUpdate);
+ }
+ CRect viewSize (pV->size);
+ drawBackgroundRect (pContext, viewSize);
+ pV->update (pContext);
+ if (child)
+ child->setMode (oldMode);
+ }
+ ENDFOR
+
+ restoreDrawContext (pContext, save);
+ }
+#endif
+ setDirty (false);
+ break;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+void CViewContainer::looseFocus (CDrawContext *pContext)
+{
+ FOREACHSUBVIEW
+ pV->looseFocus (pContext);
+ ENDFOR
+}
+
+//-----------------------------------------------------------------------------
+void CViewContainer::takeFocus (CDrawContext *pContext)
+{
+ FOREACHSUBVIEW
+ pV->takeFocus (pContext);
+ ENDFOR
+}
+
+//-----------------------------------------------------------------------------
+bool CViewContainer::advanceNextFocusView (CView* oldFocus, bool reverse)
+{
+ bool foundOld = false;
+ FOREACHSUBVIEW_REVERSE(reverse)
+ if (oldFocus && !foundOld)
+ {
+ if (oldFocus == pV)
+ {
+ foundOld = true;
+ continue;
+ }
+ }
+ else
+ {
+ if (pV->wantsFocus ())
+ {
+ getFrame ()->setFocusView (pV);
+ return true;
+ }
+ else if (pV->isTypeOf ("CViewContainer"))
+ {
+ if (((CViewContainer*)pV)->advanceNextFocusView (0, reverse))
+ return true;
+ }
+ }
+ ENDFOR
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+bool CViewContainer::isDirty () const
+{
+ if (bDirty)
+ return true;
+
+ CRect viewSize (size);
+ viewSize.offset (-size.left, -size.top);
+
+ FOREACHSUBVIEW
+ if (pV->isDirty ())
+ {
+ CRect r (pV->size);
+ r.bound (viewSize);
+ if (r.getWidth () > 0 && r.getHeight () > 0)
+ return true;
+ }
+ ENDFOR
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+CView *CViewContainer::getCurrentView () const
+{
+ if (!pParentFrame)
+ return 0;
+
+ // get the current position
+ CPoint where;
+ pParentFrame->getCurrentLocation (where);
+
+ frameToLocal (where);
+
+ CCView *pSv = pLastView;
+ while (pSv)
+ {
+ CView *pV = pSv->pView;
+ if (pV && where.isInside (pV->mouseableArea))
+ return pV;
+ pSv = pSv->pPrevious;
+ }
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+CView *CViewContainer::getViewAt (const CPoint& p, bool deep) const
+{
+ if (!pParentFrame)
+ return 0;
+
+ CPoint where (p);
+
+ // convert to relativ pos
+ where.offset (-size.left, -size.top);
+
+ CCView *pSv = pLastView;
+ while (pSv)
+ {
+ CView *pV = pSv->pView;
+ if (pV && where.isInside (pV->mouseableArea))
+ {
+ if (deep)
+ {
+ if (pV->isTypeOf ("CViewContainer"))
+ return ((CViewContainer*)pV)->getViewAt (where, deep);
+ }
+ return pV;
+ }
+ pSv = pSv->pPrevious;
+ }
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+CPoint& CViewContainer::frameToLocal (CPoint& point) const
+{
+ point.offset (-size.left, -size.top);
+ if (pParentView && pParentView->isTypeOf ("CViewContainer"))
+ return pParentView->frameToLocal (point);
+ return point;
+}
+
+//-----------------------------------------------------------------------------
+CPoint& CViewContainer::localToFrame (CPoint& point) const
+{
+ point.offset (size.left, size.top);
+ if (pParentView && pParentView->isTypeOf ("CViewContainer"))
+ return pParentView->localToFrame (point);
+ return point;
+}
+
+//-----------------------------------------------------------------------------
+bool CViewContainer::removed (CView* parent)
+{
+ if (pOffscreenContext)
+ pOffscreenContext->forget ();
+ pOffscreenContext = 0;
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+bool CViewContainer::attached (CView* view)
+{
+ // create offscreen bitmap
+ if (!pOffscreenContext && bDrawInOffscreen)
+ pOffscreenContext = new COffscreenContext (pParentFrame, (long)size.width (), (long)size.height (), kBlackCColor);
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+void CViewContainer::useOffscreen (bool b)
+{
+ bDrawInOffscreen = b;
+
+ if (!bDrawInOffscreen && pOffscreenContext)
+ {
+ pOffscreenContext->forget ();
+ pOffscreenContext = 0;
+ }
+}
+
+//-----------------------------------------------------------------------------
+void CViewContainer::modifyDrawContext (CCoord save[4], CDrawContext* pContext)
+{
+ // store
+ save[0] = pContext->offsetScreen.h;
+ save[1] = pContext->offsetScreen.v;
+ save[2] = pContext->offset.h;
+ save[3] = pContext->offset.v;
+
+ pContext->offsetScreen.h += size.left;
+ pContext->offsetScreen.v += size.top;
+ pContext->offset.h += size.left;
+ pContext->offset.v += size.top;
+}
+
+//-----------------------------------------------------------------------------
+void CViewContainer::restoreDrawContext (CDrawContext* pContext, CCoord save[4])
+{
+ // restore
+ pContext->offsetScreen.h = save[0];
+ pContext->offsetScreen.v = save[1];
+ pContext->offset.h = save[2];
+ pContext->offset.v = save[3];
+}
+
+#if DEBUG
+static long _debugDumpLevel = 0;
+//-----------------------------------------------------------------------------
+void CViewContainer::dumpInfo ()
+{
+ static const char* modeString[] = { "Normal Update Mode", "Only Dirty Update Mode"};
+ DebugPrint ("CViewContainer: Mode: %s, Offscreen:%s ", modeString[mode], bDrawInOffscreen ? "Yes" : "No");
+ CView::dumpInfo ();
+}
+
+//-----------------------------------------------------------------------------
+void CViewContainer::dumpHierarchy ()
+{
+ _debugDumpLevel++;
+ FOREACHSUBVIEW
+ for (long i = 0; i < _debugDumpLevel; i++)
+ DebugPrint ("\t");
+ pV->dumpInfo ();
+ DebugPrint ("\n");
+ if (pV->isTypeOf ("CViewContainer"))
+ ((CViewContainer*)pV)->dumpHierarchy ();
+ ENDFOR
+ _debugDumpLevel--;
+}
+
+#endif
+
+
+//-----------------------------------------------------------------------------
+// CBitmap Implementation
+//-----------------------------------------------------------------------------
+/*! @class CBitmap
+@section cbitmap_alphablend Alpha Blend and Transparency
+With Version 3.0 of VSTGUI it is possible to use alpha blended bitmaps. This comes free on Mac OS X and with Windows you need to include libpng.
+Per default PNG images will be rendered alpha blended. If you want to use a transparency color with PNG Bitmaps, you need to call setNoAlpha(true) on the bitmap and set the transparency color.
+@section cbitmap_macos Classic Apple Mac OS
+The Bitmaps are PICTs and stored inside the resource fork.
+@section cbitmap_macosx Apple Mac OS X
+The Bitmaps can be of type PNG, JPEG, PICT, BMP and are stored in the Resources folder of the plugin bundle.
+They must be named bmp00100.png (or bmp00100.jpg, etc). The number is the resource id.
+@section cbitmap_windows Microsoft Windows
+The Bitmaps are .bmp files and must be included in the plug (usually using a .rc file).
+It's also possible to use png as of version 3.0 if you define the macro USE_LIBPNG and include the libpng and zlib libraries/sources to your project.
+*/
+CBitmap::CBitmap (AEffGUIEditor& editor, const char* filename)
+ : resourceID (resourceID), width (0), height (0), noAlpha (true)
+{
+#if DEBUG
+ gNbCBitmap++;
+#endif
+
+ bool found = false;
+ long i = 0;
+ long ncolors, cpp;
+
+ pHandle = 0;
+ pMask = 0;
+
+ if (editor.getBundlePath() == NULL) {
+ std::cerr << "ERROR: No bundle path set, unable to load images" << std::endl;
+ } else {
+ std::string path = std::string(editor.getBundlePath()) + filename;
+ if (openPng(path.c_str())) // reads width, height
+ closePng();
+ }
+
+ setTransparentColor (kTransparentCColor);
+
+#if DEBUG
+ gBitmapAllocation += (long)height * (long)width;
+#endif
+}
+
+//-----------------------------------------------------------------------------
+CBitmap::CBitmap (CFrame &frame, CCoord width, CCoord height)
+ : width (width), height (height), noAlpha (true), pMask (0)
+{
+#if DEBUG
+ gNbCBitmap++;
+#endif
+
+ pHandle = (void*) XCreatePixmap (display,
+ frame.getBackBuffer (),
+ width,
+ height,
+ frame.getDepth ());
+
+ setTransparentColor (kTransparentCColor);
+}
+
+//-----------------------------------------------------------------------------
+CBitmap::CBitmap ()
+ : resourceID (0)
+ , width (0)
+ , height (0)
+ , noAlpha (true)
+{
+ pMask = 0;
+ pHandle = 0;
+}
+
+//-----------------------------------------------------------------------------
+CBitmap::~CBitmap ()
+{
+ dispose ();
+}
+
+//-----------------------------------------------------------------------------
+void CBitmap::dispose ()
+{
+#if DEBUG
+ gNbCBitmap--;
+ gBitmapAllocation -= (long)height * (long)width;
+#endif
+
+ if (pHandle)
+ XFreePixmap (display, (Pixmap)pHandle);
+ if (pMask)
+ XFreePixmap (display, (Pixmap)pMask);
+
+ pHandle = 0;
+ pMask = 0;
+
+ width = 0;
+ height = 0;
+
+}
+
+//-----------------------------------------------------------------------------
+void *CBitmap::getHandle () const
+{
+ return pHandle;
+}
+
+//-----------------------------------------------------------------------------
+bool CBitmap::loadFromResource (long resourceID)
+{
+ dispose ();
+ fprintf (stderr, "CBitmap::loadFromResource not implemented\n");
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+bool CBitmap::loadFromPath (const void* platformPath)
+{
+ if (pHandle != NULL) {
+ dispose ();
+ closePng ();
+ }
+
+ bool success = openPng ((char*)platformPath);
+ if (success)
+ closePng ();
+
+ return success;
+}
+
+//-----------------------------------------------------------------------------
+bool CBitmap::isLoaded () const
+{
+ return (pHandle != NULL);
+}
+
+//-----------------------------------------------------------------------------
+void CBitmap::draw (CDrawContext *pContext, CRect &rect, const CPoint &offset)
+{
+ if (!pHandle)
+ {
+ // the first time try to decode the pixmap
+ pHandle = createPixmapFromPng (pContext);
+ if (!pHandle)
+ return;
+ }
+
+ CFrame* frame = pContext->pFrame;
+
+ XCopyArea (display,
+ (Drawable) pHandle,
+ (Drawable) frame->getBackBuffer(),
+ (GC) frame->getGC(),
+ offset.h,
+ offset.v,
+ std::min (rect.width (), getWidth()),
+ std::min (rect.height (), getHeight()),
+ rect.left + pContext->offset.h,
+ rect.top + pContext->offset.v);
+}
+
+//-----------------------------------------------------------------------------
+void CBitmap::drawTransparent (CDrawContext *pContext, CRect &rect, const CPoint &offset)
+{
+ if (!pHandle)
+ {
+ // the first time try to decode the pixmap
+ pHandle = createPixmapFromPng (pContext);
+ if (!pHandle)
+ return;
+ }
+
+ CFrame* frame = pContext->pFrame;
+
+ if (pMask == 0)
+ {
+ // get image from the pixmap
+ XImage* image = XGetImage (display, (Drawable)pHandle,
+ 0, 0, width, height, AllPlanes, ZPixmap);
+ assert (image);
+
+ // create the bitmap mask
+ pMask = (void*) XCreatePixmap (display, (Drawable)frame->getWindow(),
+ width, height, 1);
+ assert (pMask);
+
+ // create a associated GC
+ XGCValues values;
+ values.foreground = 1;
+ GC gc = XCreateGC (display, (Drawable)pMask, GCForeground, &values);
+
+ // clear the mask
+ XFillRectangle (display, (Drawable)pMask, gc, 0, 0, width, height);
+
+ // get the transparent color index
+ int color = pContext->getIndexColor (transparentCColor);
+
+ // inverse the color
+ values.foreground = 0;
+ XChangeGC (display, gc, GCForeground, &values);
+
+ // compute the mask
+ XPoint *points = new XPoint [height * width];
+ int x, y, nbPoints = 0;
+ switch (image->depth)
+ {
+ case 8:
+ for (y = 0; y < height; y++)
+ {
+ char* src = image->data + (y * image->bytes_per_line);
+
+ for (x = 0; x < width; x++)
+ {
+ if (src[x] == color)
+ {
+ points[nbPoints].x = x;
+ points[nbPoints].y = y;
+ nbPoints++;
+ }
+ }
+ }
+ break;
+
+ case 24: {
+ int bytesPerPixel = image->bits_per_pixel >> 3;
+ char *lp = image->data;
+ for (y = 0; y < height; y++)
+ {
+ char* cp = lp;
+ for (x = 0; x < width; x++)
+ {
+ if (*(int*)cp == color)
+ {
+ points[nbPoints].x = x;
+ points[nbPoints].y = y;
+ nbPoints++;
+ }
+ cp += bytesPerPixel;
+ }
+ lp += image->bytes_per_line;
+ }
+ } break;
+
+ default :
+ break;
+ }
+
+ XDrawPoints (display, (Drawable)pMask, gc,
+ points, nbPoints, CoordModeOrigin);
+
+ // free
+ XFreeGC (display, gc);
+ delete []points;
+
+ // delete
+ XDestroyImage (image);
+ }
+
+ // set the new clipmask
+ XGCValues value;
+ value.clip_mask = (Pixmap)pMask;
+ value.clip_x_origin = (rect.left + pContext->offset.h) - offset.h;
+ value.clip_y_origin = (rect.top + pContext->offset.v) - offset.v;
+
+ XChangeGC (display,
+ (GC) /*frame->getGC(),*/ pContext->pSystemContext,
+ GCClipMask | GCClipXOrigin | GCClipYOrigin,
+ &value);
+
+ XCopyArea (display,
+ (Drawable) pHandle,
+ (Drawable) frame->getBackBuffer(),
+ (GC) frame->getGC(),
+ offset.h,
+ offset.v,
+ rect.width (),
+ rect.height (),
+ rect.left + pContext->offset.h,
+ rect.top + pContext->offset.v);
+
+ // unset the clipmask
+ XSetClipMask (display, (GC)frame->getGC(), None);
+}
+
+//-----------------------------------------------------------------------------
+void CBitmap::drawAlphaBlend (CDrawContext *pContext, CRect &rect, const CPoint &offset, unsigned char alpha)
+{
+ std::cout << "CBitmap::drawAlphaBlend (not implemented!)" << std::endl;
+}
+
+//-----------------------------------------------------------------------------
+void CBitmap::setTransparentColor (const CColor color)
+{
+ transparentCColor = color;
+}
+
+//-----------------------------------------------------------------------------
+void CBitmap::setTransparencyMask (CDrawContext* pContext, const CPoint& offset)
+{
+ // todo: implement me!
+}
+
+
+//-----------------------------------------------------------------------------
+bool CBitmap::openPng (const char* path)
+{
+ assert(path);
+
+ FILE* fp = fopen(path, "rb");
+ if (!fp) {
+ fprintf(stderr, "Unable to open file %s\n", path);
+ return false;
+ }
+
+ png_byte header[8];
+ fread(header, 1, 8, fp);
+ if (png_sig_cmp(header, 0, 8)) {
+ fprintf(stderr, "File not recognized as a PNG image");
+ return false;
+ }
+
+ pngRead = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!pngRead) {
+ fprintf(stderr, "Unable to initialize libpng\n");
+ return false;
+ }
+
+ pngInfo = png_create_info_struct(pngRead);
+ if (!pngInfo) {
+ png_destroy_read_struct(&pngRead, NULL, NULL);
+ return false;
+ }
+
+ png_init_io(pngRead, fp);
+ png_set_sig_bytes(pngRead, 8);
+
+ png_read_info(pngRead, pngInfo);
+
+ width = pngInfo->width;
+ height = pngInfo->height;
+
+ pngFp = fp;
+ pngRead = pngRead;
+ pngPath = path;
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+bool CBitmap::closePng ()
+{
+ png_destroy_read_struct(&pngRead, &pngInfo, NULL);
+ fclose(pngFp);
+ pngFp = NULL;
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+void* CBitmap::createPixmapFromPng (CDrawContext *pContext)
+{
+ if (!openPng(pngPath.c_str()))
+ return NULL;
+
+ assert(width > 0 && height > 0);
+
+ png_byte** rows = (png_byte**)malloc(height * sizeof(png_byte*));
+ for (int i = 0; i < height; ++i)
+ rows[i] = (png_byte*)(malloc(pngInfo->width * sizeof(uint32_t)));
+
+ png_read_image(pngRead, rows);
+
+ CFrame* frame = pContext->pFrame;
+
+ Pixmap p = XCreatePixmap(display, frame->getBackBuffer(),
+ pngInfo->width, pngInfo->height, 24);
+
+ XGCValues values;
+ values.foreground = 0xFFFFFFFF;
+
+ // Draw
+ GC gc = XCreateGC (display, p, GCForeground, &values);
+ for (unsigned y = 0; y < pngInfo->height; y++) {
+ for (unsigned x = 0; x < pngInfo->width; ++x) {
+ char r = rows[y][(x*3)];
+ char g = rows[y][(x*3)+1];
+ char b = rows[y][(x*3)+2];
+ uint32_t color = (r << 16) + (g << 8) + b;
+ XSetForeground(display, gc, color);
+ XDrawPoint(display, p, gc, x, y);
+ }
+ }
+ XFreeGC (display, gc);
+
+ closePng();
+
+ return (void*)p;
+}
+
+//-----------------------------------------------------------------------------
+// CDragContainer Implementation
+//-----------------------------------------------------------------------------
+CDragContainer::CDragContainer (void* platformDrag)
+: platformDrag (platformDrag)
+, nbItems (0)
+, iterator (0)
+, lastItem (0)
+{
+}
+
+//-----------------------------------------------------------------------------
+CDragContainer::~CDragContainer ()
+{
+ if (lastItem)
+ {
+ free (lastItem);
+ lastItem = 0;
+ }
+}
+
+//-----------------------------------------------------------------------------
+long CDragContainer::getType (long idx) const
+{
+ // not implemented
+ return kUnknown;
+}
+
+//-----------------------------------------------------------------------------
+void* CDragContainer::first (long& size, long& type)
+{
+ iterator = 0;
+ return next (size, type);
+}
+
+//-----------------------------------------------------------------------------
+void* CDragContainer::next (long& size, long& type)
+{
+ if (lastItem)
+ {
+ free (lastItem);
+ lastItem = 0;
+ }
+ size = 0;
+ type = kUnknown;
+
+ // not implemented
+
+ return NULL;
+}
+
+} // namespace VSTGUI
+
+//-----------------------------------------------------------------------------
+// return a degre value between [0, 360 * 64[
+static long convertPoint2Angle (CPoint &pm, CPoint &pt)
+{
+ long angle;
+ if (pt.h == pm.h)
+ {
+ if (pt.v < pm.v)
+ angle = 5760; // 90 * 64
+ else
+ angle = 17280; // 270 * 64
+ }
+ else if (pt.v == pm.v)
+ {
+ if (pt.h < pm.h)
+ angle = 11520; // 180 * 64
+ else
+ angle = 0;
+ }
+ else
+ {
+ // 3666.9299 = 180 * 64 / pi
+ angle = (long)(3666.9298 * atan ((double)(pm.v - pt.v) / (double)(pt.h - pm.h)));
+
+ if (pt.v < pm.v)
+ {
+ if (pt.h < pm.h)
+ angle += 11520; // 180 * 64
+ }
+ else
+ {
+ if (pt.h < pm.h)
+ angle += 11520; // 180 * 64
+ else
+ angle += 23040; // 360 * 64
+ }
+ }
+ return angle;
+}
+
+
+
+#if !PLUGGUI
+//-----------------------------------------------------------------------------
+// CFileSelector Implementation
+//-----------------------------------------------------------------------------
+#define stringAnyType "Any Type (*.*)"
+#define stringAllTypes "All Types: ("
+#define stringSelect "Select"
+#define stringCancel "Cancel"
+#define stringLookIn "Look in"
+#define kPathMax 1024
+
+namespace VSTGUI {
+
+//-----------------------------------------------------------------------------
+CFileSelector::CFileSelector (AudioEffectX* effect)
+: effect (effect), vstFileSelect (0)
+{}
+
+//-----------------------------------------------------------------------------
+CFileSelector::~CFileSelector ()
+{
+ if (vstFileSelect)
+ {
+ if (effect && effect->canHostDo ("closeFileSelector"))
+ effect->closeFileSelector (vstFileSelect);
+ else
+ {
+ if (vstFileSelect->reserved == 1 && vstFileSelect->returnPath)
+ {
+ delete []vstFileSelect->returnPath;
+ vstFileSelect->returnPath = 0;
+ vstFileSelect->sizeReturnPath = 0;
+ }
+ if (vstFileSelect->returnMultiplePaths)
+ {
+ for (long i = 0; i < vstFileSelect->nbReturnPath; i++)
+ {
+ delete []vstFileSelect->returnMultiplePaths[i];
+ vstFileSelect->returnMultiplePaths[i] = 0;
+ }
+ delete[] vstFileSelect->returnMultiplePaths;
+ vstFileSelect->returnMultiplePaths = 0;
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+long CFileSelector::run (VstFileSelect *vstFileSelect_)
+{
+ vstFileSelect = vstFileSelect_;
+ vstFileSelect->nbReturnPath = 0;
+ vstFileSelect->returnPath[0] = 0;
+
+ if (effect
+ && effect->canHostDo ("openFileSelector")
+ && effect->canHostDo ("closeFileSelector"))
+ {
+ if (effect->openFileSelector (vstFileSelect))
+ return vstFileSelect->nbReturnPath;
+ }
+ return 0;
+}
+
+} // namespace VSTGUI
+
+//-----------------------------------------------------------------------------
+#endif // !PLUGGUI
+//-----------------------------------------------------------------------------
+