home *** CD-ROM | disk | FTP | other *** search
- //----------------------------------------------------------------------------
- // ObjectWindows
- // Copyright (c) 1991, 1995 by Borland International, All Rights Reserved
- //
- // $Revision: 10.13 $
- //
- // Example paint program
- //----------------------------------------------------------------------------
- #include <owl/pch.h>
- #include <owl/applicat.h>
- #include <owl/dc.h>
- #include <owl/dibitmap.h>
- #include <owl/gdiobjec.h>
- #include <owl/decframe.h>
- #include <owl/chooseco.h>
- #include <owl/choosefo.h>
- #include <owl/opensave.h>
- #include <owl/printdia.h>
- #include <owl/scroller.h>
- #include <owl/controlb.h>
- #include <owl/floatfra.h>
- #include <owl/toolbox.h>
- #include <owl/buttonga.h>
- #include <owl/editfile.rh>
- #include <stdio.h>
- #include <dir.h>
- #include "paint.rh"
- #include "dibattr.h"
-
- DIAG_DEFINE_GROUP(PaintDrw,1,0); // drawing tracing (set level to 1 for mouse)
- DIAG_DEFINE_GROUP(PaintCmd,1,0); // command tracing
-
- //
- // Build options
- //
- //#define USE_LINEBAR // Comment out for line gadgets instead of line bar
- //#define USE_TOOLBAR // Uncomment out to have non-floating toolbar
- #define PARALLEL_PEN // To enable parallel line drawing with pen tool
-
- const int DefWidth = 640;
- const int DefHeight = 480;
- uint32 DefNColors= 0; // fill in with screen device info
- const int DefPenSize= 3;
-
- const TColor DefPalette[] = {
- 0x000000L, 0xFFFFFFL, 0x7F7F7FL, 0xC0C0C0L,
- 0x00007FL, 0x007F00L, 0x007F7FL, 0x7F0000L,
- 0x7F007FL, 0x7F7F00L, 0x0000FFL, 0x00FF00L,
- 0x00FFFFL, 0xFF0000L, 0xFF00FFL, 0xFFFF00L,
- };
-
- const int CM_TOOL = 300;
- const int CM_LINE = 400;
- const int ToolCount = 6;
-
- const int ID_CANVAS = 101;
- const int ID_PALETTE= 102;
-
- #if defined(USE_LINEBAR)
- const int LineCount = 8;
- const int LineBarWidth = LineCount * 4 + 6 + (1 + 2 + 3 + 4 + 5 + 7 + 9 + 12);
- const int LineWidth[LineCount] = { 1, 2, 3, 4, 5, 7, 9, 12 };
- #endif
-
-
- //----------------------------------------------------------------------------
-
- class TDrawTool;
-
- //
- //
- //
- struct TState {
- TDrawTool* DrawTool;
- TDC* DC;
- TPalette* Palette;
- TDib* Dib;
- TBitmap* Bitmap;
- int PenSize;
- int FgColor;
- int BgColor;
- string Name;
- string Title;
- bool Modified;
- };
-
- //
- //
- //
- class TDrawTool {
- public:
- TDrawTool(const char* name);
-
- void MouseDown(TWindow& window, const TPoint& point, TState* state);
- void MouseMove(const TPoint& Point);
- void MouseUp();
-
- const char* GetName() {return Name;}
-
- protected:
- virtual void DrawBegin(const TPoint& point) {}
- virtual void DrawTo(const TPoint& point) {}
- virtual void DrawEnd() {}
- virtual bool UsesPenOnly() {return false;}
-
- TCursor* Cursor;
- TIcon* Icon;
- TState* State;
- TWindow* Window;
- TPen* Pen;
- TBrush* Brush;
- TDC* DC;
- TPoint LastPoint;
- TRect Bounds;
-
- private:
- const char* Name;
- };
-
- //
- //
- //
- class TPenTool : public TDrawTool {
- public:
- TPenTool(const char* name) : TDrawTool(name) {}
-
- protected:
- virtual void DrawBegin(const TPoint& point);
- virtual void DrawTo(const TPoint& point);
- virtual void DrawEnd();
- virtual bool UsesPenOnly() {return true;}
-
- #if defined(PARALLEL_PEN)
- TPalette* TmpPalette;
- #endif
- };
-
- //
- //
- //
- class TFillTool : public TDrawTool {
- public:
- TFillTool(const char* name) : TDrawTool(name) {}
- protected:
- virtual void DrawBegin(const TPoint& point);
- };
-
- class TBoxTool : public TDrawTool {
- public:
- TBoxTool(const char* name, bool filled)
- : TDrawTool(name), Filled(filled) {}
-
- protected:
- virtual void DrawBegin(const TPoint& point);
- virtual void DrawTo(const TPoint& point);
- virtual void DrawEnd();
- virtual void DrawObject(TDC& dc) {}
-
- protected:
- bool Filled;
- int X1;
- int Y1;
- int X2;
- int Y2;
- };
-
- class TRectTool : public TBoxTool {
- public:
- TRectTool(const char* name, bool filled) : TBoxTool(name, filled) {}
- protected:
- virtual void DrawObject(TDC& dc);
- };
-
- class TEllipseTool : public TBoxTool {
- public:
- TEllipseTool(const char* name, bool filled) : TBoxTool(name, filled) {}
- protected:
- virtual void DrawObject(TDC& dc);
- };
-
- //----------------------------------------------------------------------------
-
- class TPaletteWindow : public TWindow {
- public:
- TPaletteWindow(TWindow* parent, TState* state);
- void SelectColor(TPoint& point, int& color);
-
- protected:
- void Paint(TDC&, bool, TRect&);
-
- void EvSize(UINT, TSize&);
- void EvLButtonDown(UINT modKeys, TPoint& point);
- void EvLButtonDblClk(UINT modKeys, TPoint&);
- void EvRButtonDown(UINT modKeys, TPoint& point);
- void EvRButtonDblClk(UINT modKeys, TPoint& point);
- LRESULT EvSetRGB(TParam1, TParam2);
-
- private:
- TState* State;
- bool Horz;
- int Cx; // Count of panes in the X direction
- int Cy; // Count of panes in the Y direction
- int Dx; // Size of a pane in the X direction
- int Dy; // Size of a pane in the Y direction
-
- DECLARE_RESPONSE_TABLE(TPaletteWindow);
- };
-
- DEFINE_RESPONSE_TABLE1(TPaletteWindow, TWindow)
- EV_WM_SIZE,
- EV_WM_LBUTTONDOWN,
- EV_WM_LBUTTONDBLCLK,
- EV_WM_RBUTTONDOWN,
- EV_WM_RBUTTONDBLCLK,
- EV_REGISTERED(SETRGBSTRING, EvSetRGB),
- END_RESPONSE_TABLE;
-
- //----------------------------------------------------------------------------
-
- //
- // A slightly customized floating frame for use as our tool & style button
- // palettes.
- //
- class TButtonPalette : public TFloatingFrame {
- public:
- TButtonPalette(TWindow* parent,
- char* title = 0,
- TWindow* clientWnd = 0,
- TModule* module = 0);
-
- private:
- void SetupWindow();
- void CleanupWindow();
- void EvClose();
-
- DECLARE_RESPONSE_TABLE(TButtonPalette);
- };
-
- DEFINE_RESPONSE_TABLE1(TButtonPalette, TFloatingFrame)
- EV_WM_CLOSE,
- END_RESPONSE_TABLE;
-
- TButtonPalette::TButtonPalette(TWindow* parent, char* title,
- TWindow* clientWnd, TModule* module)
- :
- TFloatingFrame(parent, title, clientWnd, true, DefaultCaptionHeight, true,
- module)
- {
- }
-
- //
- // Supply a reasonable startup position relative to our Parent (owner actually)
- //
- void
- TButtonPalette::SetupWindow()
- {
- TFloatingFrame::SetupWindow();
-
- if (Attr.X < 0 || Attr.Y < 0) {
- TRect parentRect;
- GetParentO()->GetWindowRect(parentRect);
- SetWindowPos(0, parentRect.left+10, parentRect.top+10, 0, 0,
- SWP_NOSIZE | SWP_NOZORDER);
- }
- }
-
- //
- // Remember latest position when we are destroyed, so we can reappear in the
- // same place when re-enabled.
- //
- void
- TButtonPalette::CleanupWindow()
- {
- TRect rect;
- GetWindowRect(rect);
- Attr.X = rect.left;
- Attr.Y = rect.top;
-
- TFloatingFrame::CleanupWindow();
- }
-
- //
- // Override EvClose to keep TWindow from having us deleted. We want to keep the
- // OWL object around even when the window is destroyed.
- //
- void
- TButtonPalette::EvClose()
- {
- CloseWindow();
- }
-
- //----------------------------------------------------------------------------
-
- #if defined(USE_LINEBAR)
- class TLineBar : public TWindow {
- public:
- TLineBar(TWindow* parent, TState* state);
-
- void Paint(TDC&, bool, TRect&);
- void EvLButtonDown(UINT modKeys, TPoint& point);
-
- private:
- TState* State;
- void Notch(TDC& dc, int x, int w, int y, int dy);
-
- DECLARE_RESPONSE_TABLE(TLineBar);
- };
-
- DEFINE_RESPONSE_TABLE1(TLineBar, TWindow)
- EV_WM_LBUTTONDOWN,
- END_RESPONSE_TABLE;
- #endif
-
- //----------------------------------------------------------------------------
-
- //
- // Given the bits-per-pixel depth of a DIB or a display device, return
- // the maximum number of colors that DIB or device could use.
- //
- uint32 ColorCapacity(uint depth)
- {
- switch (depth) {
- case 1: return 2;
- case 2: return 4;
- case 4: return 16;
- case 8: return 256;
- case 16: return 65536L;
- default: return 16777216L;
- }
- }
-
- //----------------------------------------------------------------------------
-
- class TCanvas : public TWindow {
- public:
- TCanvas();
- ~TCanvas();
-
- TState State;
-
- protected:
- // Override TWindow virtuals
- //
- void SetupWindow();
- bool CanClose();
-
- bool AbandonOk();
- void SetupDib(TDib* dib, const char* fileName, const char* fileTitle);
- void NewDib(int width, int height, uint32 nColors);
- void OpenDib(const char* fileName, const char* fileTitle);
- bool SaveDib(const char* fileName);
-
- void UpdateCaption();
- void AdjustScroller();
- void Paint(TDC&, bool, TRect&);
-
- void EvSize(UINT, TSize&);
- void EvLButtonDown(UINT modKeys, TPoint& point);
- void EvLButtonUp(UINT modKeys, TPoint& point);
- void EvMouseMove(UINT modKeys, TPoint& point);
- void EvDropFiles(TDropInfo dropInfo);
-
- void CmFileNew();
- void CmFileOpen();
- void CmFileSave();
- void CmFileSaveAs();
- void CmFilePrint();
- void CmFilePrintSetup();
-
- void CmViewTools();
- void CeViewTools(TCommandEnabler& ce);
- void CmViewLines();
- void CeViewLines(TCommandEnabler& ce);
-
- void CmTool(TParam1);
- void CmLine(TParam1);
-
- TPrintDialog::TData PrintData;
-
- private:
- bool Drawing;
- TDrawTool* Tools[ToolCount];
-
- TButtonPalette* ToolsPal;
- TButtonPalette* LinesPal;
-
- DECLARE_RESPONSE_TABLE(TCanvas);
- };
-
- DEFINE_RESPONSE_TABLE1(TCanvas, TWindow)
- EV_WM_SIZE,
- EV_WM_LBUTTONDOWN,
- EV_WM_LBUTTONUP,
- EV_WM_MOUSEMOVE,
- EV_WM_DROPFILES,
- EV_COMMAND_AND_ID(CM_TOOL+0, CmTool),
- EV_COMMAND_AND_ID(CM_TOOL+1, CmTool),
- EV_COMMAND_AND_ID(CM_TOOL+2, CmTool),
- EV_COMMAND_AND_ID(CM_TOOL+3, CmTool),
- EV_COMMAND_AND_ID(CM_TOOL+4, CmTool),
- EV_COMMAND_AND_ID(CM_TOOL+5, CmTool),
- EV_COMMAND_AND_ID(CM_LINE+1, CmLine),
- EV_COMMAND_AND_ID(CM_LINE+3, CmLine),
- EV_COMMAND_AND_ID(CM_LINE+5, CmLine),
- EV_COMMAND_AND_ID(CM_LINE+7, CmLine),
- EV_COMMAND_AND_ID(CM_LINE+9, CmLine),
- EV_COMMAND_AND_ID(CM_LINE+11, CmLine),
- EV_COMMAND(CM_FILENEW, CmFileNew),
- EV_COMMAND(CM_FILEOPEN, CmFileOpen),
- EV_COMMAND(CM_FILESAVE, CmFileSave),
- EV_COMMAND(CM_FILESAVEAS, CmFileSaveAs),
- EV_COMMAND(CM_FILEPRINT, CmFilePrint),
- EV_COMMAND(CM_FILEPRINTERSETUP, CmFilePrintSetup),
- EV_COMMAND(CM_VIEWTOOLS, CmViewTools),
- EV_COMMAND_ENABLE(CM_VIEWTOOLS, CeViewTools),
- EV_COMMAND(CM_VIEWLINES, CmViewLines),
- EV_COMMAND_ENABLE(CM_VIEWLINES, CeViewLines),
- END_RESPONSE_TABLE;
-
- // --------------- TDrawTool ------------------------
-
- TDrawTool::TDrawTool(const char* name)
- :
- State(0), Window(0), Pen(0), Brush(0), DC(0), Name(name)
- {
- }
-
- void
- TDrawTool::MouseDown(TWindow& window, const TPoint& point, TState* state)
- {
- TRACEX(PaintDrw,0,"Draw " << GetName() <<
- " started at (" << point.x << "," << point.y << ")");
- Window = &window;
- State = state;
- Window->SetCapture();
-
- DC = new TClientDC(window);
-
- //
- if (UsesPenOnly()) {
- Pen = new TPen(TColor(State->FgColor), State->PenSize);
- }
- else {
- Brush = new TBrush(TColor(State->FgColor));
- Pen = new TPen(TColor(State->BgColor), State->PenSize);
- }
-
- State->DC->SelectObject(*State->Palette);
- State->DC->RealizePalette();
- State->DC->SelectObject(*Pen);
- if (Brush)
- State->DC->SelectObject(*Brush);
-
- LastPoint = point;
- Bounds = TRect(point, point);
- DrawBegin(point);
- }
-
- void
- TDrawTool::MouseMove(const TPoint& point)
- {
- TRACEX(PaintDrw,1,"Draw " << GetName() <<
- " extends to (" << point.x << "," << point.y << ")");
- Bounds |= TRect(point.x, point.y, point.x, point.y);
- DrawTo(point);
- LastPoint = point;
- }
-
- void
- TDrawTool::MouseUp()
- {
- TRACEX(PaintDrw,1,"Draw " << GetName() << " finished");
- DrawEnd();
-
- Window->ReleaseCapture();
- State->DC->RestoreObjects();
-
- delete Brush; Brush = 0;
- delete Pen; Pen = 0;
- delete DC; DC = 0;
-
- State->Modified = true;
- Window->InvalidateRect(Bounds.
- InflatedBy((State->PenSize+1)/2,(State->PenSize+1)/2), false);
- Window->UpdateWindow();
- }
-
- // --------------- TPenTool ------------------------
-
- void
- TPenTool::DrawBegin(const TPoint& point)
- {
- State->DC->MoveTo(point);
-
- // Do parallel update onto screen
- //
- #if defined(PARALLEL_PEN)
- // can't select a palette into to different device DCs
- TmpPalette = new TPalette(*State->Palette);
- DC->IntersectClipRect(TRect(TPoint(0,0), State->Dib->Size()));
- DC->SelectObject(*TmpPalette);
- DC->RealizePalette();
-
- DC->SelectObject(*Pen);
- DC->MoveTo(point);
- #endif
- }
-
- void
- TPenTool::DrawTo(const TPoint& point)
- {
- State->DC->LineTo(point);
- #if defined(PARALLEL_PEN)
- DC->LineTo(point);
- #else
- Window->InvalidateRect(TRect(LastPoint, point).Normalized().
- InflatedBy((State->PenSize+1)/2,(State->PenSize+1)/2),false);
- Window->UpdateWindow();
- #endif
- }
-
- void
- TPenTool::DrawEnd()
- {
- State->DC->RestorePen();
- #if defined(PARALLEL_PEN)
- DC->RestorePen();
- delete TmpPalette; TmpPalette = 0;
- #endif
- }
-
- // --------------- TFillTool ------------------------
-
- void
- TFillTool::DrawBegin(const TPoint& point)
- {
- TBrush fgBrush(State->FgColor);
- State->DC->SelectObject(fgBrush);
- TColor surfaceColor(State->DC->GetPixel(point));
- State->DC->ExtFloodFill(point, surfaceColor, FLOODFILLSURFACE);
- Bounds = Window->GetClientRect();
- State->DC->RestoreBrush();
- }
-
- // --------------- TBoxTool ------------------------
-
- void
- TBoxTool::DrawBegin(const TPoint& point)
- {
- X1 = X2 = point.x;
- Y1 = Y2 = point.y;
- DC->SelectStockObject(BLACK_PEN);
- DC->SelectStockObject(NULL_BRUSH);
- DC->SetROP2(R2_NOT);
- DrawObject(*DC);
- }
-
- void
- TBoxTool::DrawTo(const TPoint& point)
- {
- DrawObject(*DC);
- X2 = point.x;
- Y2 = point.y;
- DrawObject(*DC);
- }
-
- void
- TBoxTool::DrawEnd()
- {
- DrawObject(*DC);
- DC->SetROP2(R2_COPYPEN);
- State->DC->SelectObject(*Pen);
- if (Filled)
- State->DC->SelectObject(*Brush);
- else
- State->DC->SelectStockObject(NULL_BRUSH);
- DrawObject(*State->DC);
- }
-
- // --------------- TRectTool ------------------------
-
- void
- TRectTool::DrawObject(TDC& dc)
- {
- dc.Rectangle(X1, Y1, X2, Y2);
- }
-
- // --------------- TEllipseTool ------------------------
-
- void
- TEllipseTool::DrawObject(TDC& dc)
- {
- dc.Ellipse(X1, Y1, X2, Y2);
- }
-
- // --------------- TPaletteWindow ------------------------
-
- TPaletteWindow::TPaletteWindow(TWindow* parent, TState* state)
- : TWindow(parent),
- State(state)
- {
- Attr.Style |= WS_BORDER;
- Attr.W = 50;
- Attr.H = 50;
- Attr.Id = ID_PALETTE;
- }
-
- void
- TPaletteWindow::EvSize(UINT, TSize&)
- {
- TRect rect = GetClientRect();
- Horz = true; // Location==Top || Location==Bottom;
- Cx = (Horz ? 17 : 3);
- Cy = (Horz ? 3 : 17);
- Dx = rect.right / Cx;
- Dy = rect.bottom / Cy;
- if (Horz)
- Cx--;
- else
- Cy--;
- Invalidate(false);
- }
-
- void
- TPaletteWindow::Paint(TDC& dc, bool, TRect&)
- {
- dc.SelectObject(*State->Palette);
- dc.RealizePalette();
-
- TRect rect = GetClientRect();
-
- dc.SelectStockObject(BLACK_PEN);
-
- // Paint color selection cells, each with a black frame
- //
- for (int i = 0; i < 16; i++)
- for (int j = 0; j < 3; j++) {
- TBrush brush(TColor(j*16+i));
- dc.SelectObject(brush);
- TPoint p = Horz ? TPoint(i*Dx, j*Dy) : TPoint(j*Dx, i*Dy);
- dc.Rectangle(p, TSize(Dx+1, Dy+1));
- dc.RestoreBrush();
- }
-
- // Paint fore & back color display, frame first
- //
- dc.SelectStockObject(NULL_BRUSH);
- TPoint p = Horz ? TPoint(Dx*16, 0) : TPoint(0, Dy*16);
- dc.Rectangle(p, rect.BottomRight());
-
- TPen pen(TColor(State->BgColor), 5);
- dc.SelectObject(pen);
- TBrush brush(TColor(State->FgColor));
- dc.SelectObject(brush);
- p += TSize(3,3);
- dc.Rectangle(p, TPoint(rect.right-3, rect.bottom-3));
- }
-
- void
- TPaletteWindow::SelectColor(TPoint& point, int& color)
- {
- point.x /= Dx;
- point.y /= Dy;
- if (point.x < Cx && point.y < Cy) {
- int newColor = Horz ? point.x + point.y*Cx : point.x*Cy + point.y;
- if (color != newColor) {
- TColor c = State->Dib->GetColor(newColor);
-
- InvalidateRect(Horz ? TRect(TPoint(Dx*Cx, 0), GetClientRect().BottomRight()) :
- TRect(TPoint(0, Dy*Cy), GetClientRect().BottomRight()),
- false);
- color = newColor;
- }
- }
- }
-
- void
- TPaletteWindow::EvLButtonDown(UINT, TPoint& point)
- {
- SelectColor(point, State->FgColor);
- }
-
- void
- TPaletteWindow::EvLButtonDblClk(UINT, TPoint& point)
- {
- static TColor CustColors[32];
-
- int editColor = -1;
- SelectColor(point, editColor);
- if (editColor < 0)
- return;
-
- // If the DIB lacks an adjustable palette, then stop.
- //
- if (State->Dib->NumColors() == 0)
- {
- MessageBox("This DIB has no palette to change",
- GetApplication()->GetName(), MB_OK);
- return;
- }
-
- TChooseColorDialog::TData choose;
- choose.Flags = CC_RGBINIT;
- PALETTEENTRY pe;
- State->Palette->GetPaletteEntry((WORD)editColor, pe);
- choose.Color = pe;
- choose.CustColors = CustColors;
-
- if (TChooseColorDialog(this, choose).Execute() == IDOK) {
- State->Dib->SetColor(editColor, choose.Color);
- delete State->Palette;
- State->Palette = new TPalette(*State->Dib);
- Invalidate(false);
- TWindow* canvas = GetParentO()->ChildWithId(ID_CANVAS);
- if (canvas && canvas->GetHandle())
- canvas->Invalidate(false);
- }
- }
-
- void
- TPaletteWindow::EvRButtonDown(UINT, TPoint& point)
- {
- SelectColor(point, State->BgColor);
- }
-
- void
- TPaletteWindow::EvRButtonDblClk(UINT modKeys, TPoint& point)
- {
- EvLButtonDblClk(modKeys, point);
- }
-
- LRESULT
- TPaletteWindow::EvSetRGB(TParam1, TParam2)
- {
- Invalidate(false);
- return 0;
- }
-
- #if defined(USE_LINEBAR)
- // --------------- TLineBar ------------------------
-
- TLineBar::TLineBar(TWindow* parent, TState* state)
- : TWindow(parent),
- State(state)
- {
- Attr.Style |= WS_BORDER;
- Attr.W = 32;
- Attr.H = 32;
- }
-
- void
- TLineBar::Notch(TDC& dc, int x, int w, int y, int dy)
- {
- for (int l = 3; l >= 0; l--) {
- dc.MoveTo(TPoint(x + w / 2 - l, y));
- dc.LineTo(TPoint(x + w / 2 + l + 1, y));
- y += dy;
- }
- }
-
- void
- TLineBar::Paint(TDC& dc, bool, TRect&)
- {
- int x = 4;
- dc.SelectStockObject(WHITE_BRUSH);
- dc.PatBlt(TRect(0, 0, Attr.W, Attr.H));
- dc.SelectStockObject(BLACK_BRUSH);
- for (int i = 0; i < LineCount; i++) {
- int w = LineWidth[i];
- dc.PatBlt(TRect(x, 5, x + w, 25));
- if (w == State->PenSize) {
- Notch(dc, x, w, 0, 1);
- Notch(dc, x, w, 29, -1);
- }
- x += w + 4;
- }
- }
-
- void
- TLineBar::EvLButtonDown(UINT, TPoint& point)
- {
- int x = 2;
- for (int i = 0; i < LineCount; i++) {
- int w = LineWidth[i];
- if (point.x >= x && point.x < x+w+4) {
- TRACEX(PaintCmd,0,"Width = " << w);
- State->PenSize = w;
- Invalidate(false);
- return;
- }
- x += w + 4;
- }
- }
- #endif
-
- // --------------- TCanvas ------------------------
-
- TCanvas::TCanvas()
- :
- TWindow(0, 0, 0),
- Drawing(false)
- {
- State.DrawTool = 0;
- State.Dib = 0;
- State.Bitmap = 0;
- State.DC = 0;
- State.Palette = 0;
- State.PenSize = DefPenSize;
- State.FgColor = 0;
- State.BgColor = 1;
- State.Name = State.Title = "";
-
- Scroller = 0;
-
- Tools[0] = new TPenTool("Pen");
- Tools[1] = new TFillTool("Fill");
- Tools[2] = new TRectTool("Rect", false);
- Tools[3] = new TRectTool("FillRect", true);
- Tools[4] = new TEllipseTool("Ellipse", false);
- Tools[5] = new TEllipseTool("FillEllipse", true);
- State.DrawTool = Tools[0];
-
- Attr.Id = ID_CANVAS;
-
- ToolsPal = LinesPal = 0;
-
- // Set transparent background to skip EvEraseBkgnd & erase during paint
- //
- SetBkgndColor(TColor::Transparent);
- }
-
- TCanvas::~TCanvas()
- {
- delete State.DC;
- delete State.Palette;
- delete State.Dib;
- delete State.Bitmap;
-
- for (int i = 0; i < ToolCount; i++)
- delete Tools[i];
- }
-
- void
- TCanvas::SetupWindow()
- {
- TWindow::SetupWindow();
- NewDib(DefWidth, DefHeight, DefNColors);
- DragAcceptFiles(true);
-
- // Construct the toolboxes if selected.
- // Could Create() them here, or just wait for the menu selection to create
- // them
- //
- #if !defined(USE_TOOLBAR)
- TToolBox* tb = new TToolBox(GetParentO());
- tb->Insert(*new TButtonGadget(CM_TOOL+0, CM_TOOL+0, TButtonGadget::Exclusive,
- true, TButtonGadget::Down));
- tb->Insert(*new TButtonGadget(CM_TOOL+1, CM_TOOL+1, TButtonGadget::Exclusive, true));
- tb->Insert(*new TButtonGadget(CM_TOOL+2, CM_TOOL+2, TButtonGadget::Exclusive, true));
- tb->Insert(*new TButtonGadget(CM_TOOL+3, CM_TOOL+3, TButtonGadget::Exclusive, true));
- tb->Insert(*new TButtonGadget(CM_TOOL+4, CM_TOOL+4, TButtonGadget::Exclusive, true));
- tb->Insert(*new TButtonGadget(CM_TOOL+5, CM_TOOL+5, TButtonGadget::Exclusive, true));
- ToolsPal = new TButtonPalette(this, "", tb);
-
- tb = new TToolBox(GetParentO());
- tb->Insert(*new TButtonGadget(CM_LINE+1, CM_LINE+1, TButtonGadget::Exclusive,
- true, TButtonGadget::Down));
- tb->Insert(*new TButtonGadget(CM_LINE+3, CM_LINE+3, TButtonGadget::Exclusive, true));
- tb->Insert(*new TButtonGadget(CM_LINE+5, CM_LINE+5, TButtonGadget::Exclusive, true));
- tb->Insert(*new TButtonGadget(CM_LINE+7, CM_LINE+7, TButtonGadget::Exclusive, true));
- tb->Insert(*new TButtonGadget(CM_LINE+9, CM_LINE+9, TButtonGadget::Exclusive, true));
- tb->Insert(*new TButtonGadget(CM_LINE+11, CM_LINE+11, TButtonGadget::Exclusive, true));
- LinesPal = new TButtonPalette(this, "", tb);
- #endif
-
- // A scroller on the client area would be nice...
- //
- //Scroller = new TScroller(this,1,1, State.Dib->Width(), State.Dib->Height());
- SetFocus();
- }
-
- bool
- TCanvas::CanClose()
- {
- return AbandonOk();
- }
-
- bool
- TCanvas::AbandonOk()
- {
- if (!State.Modified)
- return true;
- const char msgFrmt[] = "%s\nThe image has changed.\n\n"
- "Do you want to save current changes?";
- char msg[sizeof(msgFrmt)+100];
- sprintf(msg, msgFrmt, State.Name.c_str());
- int resp = MessageBox(msg, GetApplication()->GetName(),
- MB_ICONEXCLAMATION|MB_YESNOCANCEL);
- if (resp == IDYES)
- CmFileSave();
-
- return resp != IDCANCEL;
- }
-
- //
- // Setup state info given a new dib. Assumes ownership of the dib.
- //
- void
- TCanvas::SetupDib(TDib* dib, const char* name, const char* title)
- {
- TPalette* newPalette;
-
- // Make a palette for the DIB.
- //
- try {
- newPalette = new TPalette(*dib);
- }
- catch (TGdiObject::TXGdi&) {
-
- // Probably DIB is true color and therefore lacks a color table.
- // We still need a palette object. If the current display device
- // supports palettes, then select a halftone palette because that
- // will have a good range of colors to choose from. If the
- // current display does not support palettes (because it's a high-
- // color display), just use the stock palette.
- //
- TScreenDC display;
- if (display.GetDeviceCaps(RASTERCAPS) & RC_PALETTE)
- newPalette = new THalftonePalette();
- else
- newPalette = new TPalette((HPALETTE)::GetStockObject(DEFAULT_PALETTE));
-
-
- // (There are better ways to set up a palette for rendering a
- // high-color image with a limited color set. It's preferable
- // to scan the DIB's colors and make intelligent choices about
- // which to use--that's a standard problem, and you can find
- // articles describing ways to do it.)
- }
-
- TMemoryDC* newDC = new TMemoryDC;
- TBitmap* newBM = new TBitmap(TScreenDC(), *dib, 0);
-
- SetCursor(0, IDC_WAIT);
- newDC->SelectObject(*newPalette);
- newDC->RealizePalette();
- newDC->SelectObject(*newBM);
- newDC->SetDIBits(*newBM, *dib);
- SetCursor(0, IDC_ARROW);
-
- delete State.DC;
- delete State.Palette;
- delete State.Dib;
- delete State.Bitmap;
-
- State.DC = newDC;
- State.Palette = newPalette;
- State.Dib = dib;
- State.Bitmap = newBM;
- State.Name = name;
- State.Title = title;
- State.Modified = false;
-
- UpdateCaption();
- AdjustScroller();
- TWindow* palette = GetParentO()->ChildWithId(ID_PALETTE);
- if (palette && palette->GetHandle())
- palette->Invalidate(false);
- Invalidate(false);
- }
-
- //
- // Create a new dib & setup state info
- //
- void
- TCanvas::NewDib(int width, int height, uint32 nColors)
- {
- // Construct the DIB, catching any exceptions that might occur and
- // displaying a warning
- //
- TDib* dib;
- try {
- dib = new TDib(width, height, nColors);
- }
- catch (TGdiObject::TXGdi& x) {
- MessageBox("Cannot create DIB", GetApplication()->GetName(), MB_OK);
- return;
- }
-
- // Convert number of colors supported to number of colors
- // needed in color table. For high-color images, the color
- // table size is 0.
- //
- int nColorsInTable = (int)NColors(NBits(nColors));
-
- // If a palette is needed, set up a reasonable default.
- //
- int nDefPalette = sizeof(DefPalette) / sizeof(DefPalette[0]);
- if (nColorsInTable)
- for (int i = 0; i < min(nColorsInTable, nDefPalette); i++)
- dib->SetColor(i, DefPalette[i]);
-
- SetupDib(dib, "", "(Untitled)");
-
- TBrush brush(TColor(State.BgColor));
- State.DC->SelectObject(*State.Palette);
- State.DC->RealizePalette();
- State.DC->SelectObject(brush);
- State.DC->PatBlt(TRect(TPoint(0,0), State.Dib->Size()));
- State.DC->RestoreObjects();
- }
-
- //
- // Open a dib & setup state info given a dib filename & title
- //
- void
- TCanvas::OpenDib(const char* fileName, const char* fileTitle)
- {
- TDib* dib;
- try {
- dib = new TDib(fileName);
- }
- catch (TGdiObject::TXGdi& x) {
- MessageBox("Invalid Bitmap File", GetApplication()->GetName(), MB_OK);
- return;
- }
-
- SetupDib(dib, fileName, fileTitle);
- }
-
- bool
- TCanvas::SaveDib(const char* fileName)
- {
- if (State.Bitmap) {
- delete State.Dib;
- State.Dib = new TDib(*State.Bitmap,
- // add the palette if the bitmap needs it
- State.Bitmap->BitsPixel() <= 8 ? State.Palette : 0);
- }
- if (State.Dib->WriteFile(fileName))
- return true;
- MessageBox("Disk error saving bitmap!", GetApplication()->GetName(), MB_OK);
- return false;
- }
-
- void
- TCanvas::UpdateCaption()
- {
- char captionBuffer[70];
- if (State.Dib)
- sprintf(captionBuffer, "%s - %s [%dx%dx%lu]", GetApplication()->GetName(),
- (LPCSTR)State.Title.c_str(),
- State.Dib->Width(), State.Dib->Height(),
- ColorCapacity(State.Dib->BitsPixel()));
- else
- sprintf(captionBuffer, "%s - (Bad Dib!)", GetApplication()->GetName());
- GetParentO()->SetCaption(captionBuffer);
- }
-
- void
- TCanvas::AdjustScroller()
- {
- if (!Scroller)
- return;
-
- TRect clientRect = GetClientRect();
-
- // only show scrollbars when image is larger than
- // the client area and we are not stretching to fit.
- //
- TPoint range(Max(State.Dib->Width()-clientRect.Width(), 0),
- Max(State.Dib->Height()-clientRect.Height(), 0));
- Scroller->SetRange(range.x, range.y);
- Scroller->ScrollTo(0, 0);
- if (!GetUpdateRect(clientRect, false))
- Invalidate(false);
- }
-
- void
- TCanvas::EvSize(UINT SizeType, TSize& Size)
- {
- TWindow::EvSize(SizeType, Size);
- if (SizeType != SIZEICONIC)
- AdjustScroller();
- }
-
- void
- TCanvas::Paint(TDC& dc, bool, TRect&)
- {
- TRect drect(TPoint(0,0), State.Dib->Size());
- TRect crect = GetClientRect();
- if (Scroller)
- crect += TPoint((int)Scroller->XPos, (int)Scroller->YPos);
-
- // optimize this painting!
- //TRect prect(rect);
- //drect &= prect;
- dc.SelectObject(*State.Palette);
- dc.RealizePalette();
-
- // Blit the DDB or DIB from the working DC to the screen
- //
- if (State.Bitmap)
- dc.BitBlt(drect, *State.DC, TPoint(0,0));
- else
- dc.SetDIBitsToDevice(drect, TPoint(0,0), *State.Dib);
-
- // Paint around the canvas
- //
- TBrush bkBrush(TColor::SysAppWorkspace); // or SysWindow
- dc.SelectObject(bkBrush);
- dc.PatBlt(TRect(drect.right, 0, crect.right, crect.bottom));
- dc.PatBlt(TRect(0, drect.bottom, crect.right, crect.bottom));
-
- dc.RestoreObjects();
- }
-
- void
- TCanvas::EvLButtonDown(UINT modKeys, TPoint& point)
- {
- TWindow::EvLButtonDown(modKeys, point);
- if (!Drawing) {
- Drawing = true;
- State.DrawTool->MouseDown(*this, point, &State);
- }
- }
-
- void
- TCanvas::EvMouseMove(UINT, TPoint& point)
- {
- if (Drawing)
- State.DrawTool->MouseMove(point);
- }
-
- void
- TCanvas::EvLButtonUp(UINT, TPoint& point)
- {
- if (Drawing) {
- State.DrawTool->MouseMove(point);
- State.DrawTool->MouseUp();
- Drawing = false;
- }
- }
-
- void
- TCanvas::EvDropFiles(TDropInfo dropInfo)
- {
- int totalNumberOfFiles = dropInfo.DragQueryFileCount();
- if (totalNumberOfFiles == 1 && AbandonOk()) {
- char filePath[MAXPATH+1];
- char fileTitle[MAXFILE];
- dropInfo.DragQueryFile(0, filePath, MAXPATH + 1);
- fnsplit(filePath, 0, 0, fileTitle, 0);
- OpenDib(filePath, fileTitle);
- }
- dropInfo.DragFinish();
- }
-
- void
- TCanvas::CmTool(TParam1 toolCmd)
- {
- int i = toolCmd - CM_TOOL;
- TRACEX(PaintCmd,0, "Tool = " << Tools[i]->GetName());
- State.DrawTool = Tools[i];
-
- SetCursor(GetModule(), toolCmd);
- }
-
- void
- TCanvas::CmLine(TParam1 lineCmd)
- {
- State.PenSize = lineCmd - CM_LINE;
- }
-
- void
- TCanvas::CmFileNew()
- {
- TRACEX(PaintCmd,0,"CmFileNew()");
- if (!AbandonOk())
- return;
-
- static int width = DefWidth;
- static int height = DefHeight;
- static uint32 ncolors = DefNColors;
- if (TDibAttrDialog(this, width, height, ncolors).Execute() == IDOK)
- NewDib(width, height, ncolors);
- }
-
- void
- TCanvas::CmFileOpen()
- {
- TRACEX(PaintCmd,0,"CmFileOpen()");
- if (!AbandonOk())
- return;
-
- TOpenSaveDialog::TData data (
- OFN_HIDEREADONLY|OFN_FILEMUSTEXIST|OFN_NOREADONLYRETURN,
- "Bitmap Files (*.BMP)|*.bmp|",
- 0,
- "",
- "BMP"
- );
- if (TFileOpenDialog(this, data).Execute() == IDOK) {
- char fileTitle[MAXPATH];
- TOpenSaveDialog::GetFileTitle(data.FileName, fileTitle, MAXPATH);
- OpenDib(data.FileName, fileTitle);
- }
- }
-
- void
- TCanvas::CmFileSave()
- {
- TRACEX(PaintCmd,0,"CmFileSave()");
- if (State.Modified) {
- if (!State.Name.length()) {
- CmFileSaveAs();
- return;
- }
-
- if (SaveDib(State.Name.c_str()))
- State.Modified = false;
- }
- }
-
- void
- TCanvas::CmFileSaveAs()
- {
- TRACEX(PaintCmd,0,"CmFileSaveAs()");
- TOpenSaveDialog::TData data (
- OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
- "Bitmap Files (*.BMP)|*.bmp|",
- 0,
- "",
- "BMP"
- );
- if (TFileSaveDialog(this, data).Execute() == IDOK) {
- if (SaveDib(data.FileName)) {
- State.Name = data.FileName;
- State.Modified = false;
- char fileTitle[MAXPATH];
- TOpenSaveDialog::GetFileTitle(data.FileName, fileTitle, MAXPATH);
- State.Title = fileTitle;
- UpdateCaption();
- }
- }
- }
-
- void
- TCanvas::CmFilePrint()
- {
- TRACEX(PaintCmd, 0, "CmFilePrint()");
- PrintData.Flags &= ~PD_PRINTSETUP;
- if (TPrintDialog(this, PrintData).Execute() == IDOK) {
- MessageBox("No File|Print yet...", GetApplication()->GetName(), MB_OK);
- }
- }
-
- void
- TCanvas::CmFilePrintSetup()
- {
- TRACEX(PaintCmd, 0, "CmFilePrintSetup()");
- PrintData.Flags |= PD_PRINTSETUP;
- TPrintDialog(this, PrintData, 0).Execute();
- }
-
- void
- TCanvas::CmViewTools()
- {
- if (ToolsPal)
- if (ToolsPal->GetHandle())
- ToolsPal->Destroy();
- else
- ToolsPal->Create();
- }
-
- void
- TCanvas::CeViewTools(TCommandEnabler& ce)
- {
- if (!ToolsPal)
- ce.Enable(false);
- else
- ce.SetCheck(ToolsPal->GetHandle() ?
- TCommandEnabler::Checked : TCommandEnabler::Unchecked);
- }
-
- void
- TCanvas::CmViewLines()
- {
- if (LinesPal)
- if (LinesPal->GetHandle())
- LinesPal->Destroy();
- else
- LinesPal->Create();
- }
-
- void
- TCanvas::CeViewLines(TCommandEnabler& ce)
- {
- if (!LinesPal)
- ce.Enable(false);
- else
- ce.SetCheck(LinesPal->GetHandle() ?
- TCommandEnabler::Checked : TCommandEnabler::Unchecked);
- }
-
-
- //----------------------------------------------------------------------------
-
- class TPaintApp : public TApplication {
- public:
- TPaintApp() : TApplication("OWL Paint") {}
- void InitMainWindow();
- };
-
- void TPaintApp::InitMainWindow()
- {
- TCanvas& client = *new TCanvas;
- TDecoratedFrame* frame = new TDecoratedFrame(0, Name, &client);
-
- #if defined(USE_TOOLBAR)
- TControlBar* cb = new TControlBar(frame);
- cb->Insert(*new TButtonGadget(CM_TOOL+0, CM_TOOL+0, TButtonGadget::Exclusive,
- false, TButtonGadget::Down));
- cb->Insert(*new TButtonGadget(CM_TOOL+1, CM_TOOL+1, TButtonGadget::Exclusive));
- cb->Insert(*new TButtonGadget(CM_TOOL+2, CM_TOOL+2, TButtonGadget::Exclusive));
- cb->Insert(*new TButtonGadget(CM_TOOL+3, CM_TOOL+3, TButtonGadget::Exclusive));
- cb->Insert(*new TButtonGadget(CM_TOOL+4, CM_TOOL+4, TButtonGadget::Exclusive));
- cb->Insert(*new TButtonGadget(CM_TOOL+5, CM_TOOL+5, TButtonGadget::Exclusive));
- #if !defined(USE_LINEBAR)
- cb->Insert(*new TSeparatorGadget);
- cb->Insert(*new TButtonGadget(CM_LINE+1, CM_LINE+1, TButtonGadget::Exclusive));
- cb->Insert(*new TButtonGadget(CM_LINE+3, CM_LINE+3, TButtonGadget::Exclusive,
- false, TButtonGadget::Down));
- cb->Insert(*new TButtonGadget(CM_LINE+5, CM_LINE+5, TButtonGadget::Exclusive));
- cb->Insert(*new TButtonGadget(CM_LINE+7, CM_LINE+7, TButtonGadget::Exclusive));
- cb->Insert(*new TButtonGadget(CM_LINE+9, CM_LINE+9, TButtonGadget::Exclusive));
- cb->Insert(*new TButtonGadget(CM_LINE+11, CM_LINE+11, TButtonGadget::Exclusive));
- #endif
- frame->Insert(*cb, TDecoratedFrame::Top);
- #endif
-
- frame->Insert(*new TPaletteWindow(frame, &client.State), TDecoratedFrame::Bottom);
- #if defined(USE_LINEBAR)
- frame->Insert(*new TLineBar(frame, &client.State), TDecoratedFrame::Bottom);
- #endif
-
- frame->AssignMenu("PaintMenu");
- frame->Attr.AccelTable = "PaintAccels";
- frame->SetIcon(this, "PaintIcon");
-
- SetMainWindow(frame);
- }
-
- int
- OwlMain(int /*argc*/, char* /*argv*/ [])
- {
- TScreenDC screenDC;
-
- DefNColors = ColorCapacity(screenDC.GetDeviceCaps(BITSPIXEL)*screenDC.GetDeviceCaps(PLANES));
- return TPaintApp().Run();
- }
-