root/src/apps/cortex/DiagramView/DiagramView.h
/*
 * Copyright (c) 1999-2000, Eric Moon.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR 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.
 */


// DiagramView.h (Cortex/DiagramView)
//
// * PURPOSE
//   BView and DiagramItemGroup derived class providing the
//   one and only drawing context all child DiagramItems will
//   use.
//
// * HISTORY
//   c.lenz             25sep99         Begun
//

#ifndef __DiagramView_H__
#define __DiagramView_H__

#include "DiagramItemGroup.h"

#include <Region.h>
#include <View.h>

//class BBitmap;

#include "cortex_defs.h"
__BEGIN_CORTEX_NAMESPACE

//class DiagramBox;
class DiagramWire;
class DiagramEndPoint;

class DiagramView : public BView,
                                        public DiagramItemGroup
{

public:                         // *** ctor/dtor

                                                DiagramView(
                                                        BRect frame,
                                                        const char *name,
                                                        bool multiSelection,
                                                        uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP,
                                                        uint32 flags = B_WILL_DRAW);

        virtual                         ~DiagramView();

public:                                 // *** hook functions

        // is called from MessageReceived() if a wire has been dropped
        // on the background or on an incompatible endpoint
        virtual void            connectionAborted(
                                                        DiagramEndPoint *fromWhich)
                                                { /* does nothing */ }

        // is called from MessageReceived() if an endpoint has accepted
        // a wire-drop (i.e. connection)
        virtual void            connectionEstablished(
                                                        DiagramEndPoint *fromWhich,
                                                        DiagramEndPoint *toWhich)
                                                { /* does nothing */ }

        // must be implemented to return an instance of the DiagramWire
        // derived class
        virtual DiagramWire *createWire(
                                                        DiagramEndPoint *fromWhich,
                                                        DiagramEndPoint *woWhich) = 0;

        // must be implemented to return an instance of the DiagramWire
        // derived class; this version is for temporary wires used in
        // drag & drop connecting
        virtual DiagramWire *createWire(
                                                        DiagramEndPoint *fromWhich) = 0;
                                        
        // hook called from BackgroundMouseDown() if the background was hit
        virtual void            BackgroundMouseDown(
                                                        BPoint point,
                                                        uint32 buttons,
                                                        uint32 clicks)
                                                { /* does nothing */ }

        // hook called from MouseMoved() if the mouse is floating over
        // the background (i.e. with no message attached)
        virtual void            MouseOver(
                                                        BPoint point,
                                                        uint32 transit)
                                                { /* does nothing */ }

        // hook called from MouseMoved() if a message is being dragged
        // over the background
        virtual void            MessageDragged(
                                                        BPoint point,
                                                        uint32 transit,
                                                        const BMessage *message);

        // hook called from MessageReceived() if a message has been
        // dropped over the background
        virtual void            MessageDropped(
                                                        BPoint point,
                                                        BMessage *message);

public:                                 // derived from BView

        // initial scrollbar update [e.moon 16nov99]
        virtual void            AttachedToWindow();

        // draw the background and all items
        virtual void            Draw(
                                                        BRect updateRect);

        // updates the scrollbars
        virtual void            FrameResized(
                                                        float width,
                                                        float height);

        // return data rect [c.lenz 1mar2000]
        virtual void            GetPreferredSize(
                                                        float *width,
                                                        float *height);

        // handles the messages M_SELECTION_CHANGED and M_WIRE_DROPPED
        // and passes a dropped message on to the item it was dropped on
        virtual void            MessageReceived(
                                                        BMessage *message);

        // handles the arrow keys for moving DiagramBoxes
        virtual void            KeyDown(
                                                        const char *bytes,
                                                        int32 numBytes);

        // if an item is located at the click point, this function calls
        // that items MouseDown() method; else a deselectAll() command is
        // made and rect-tracking is initiated
        virtual void            MouseDown(
                                                        BPoint point);

        // if an item is located under the given point, this function
        // calls that items MessageDragged() hook if a message is being
        // dragged, and MouseOver() if not
        virtual void            MouseMoved(
                                                        BPoint point,
                                                        uint32 transit,
                                                        const BMessage *message);

        // ends rect-tracking and wire-tracking
        virtual void            MouseUp(
                                                        BPoint point);

public:                                 // *** derived from DiagramItemGroup

        // extends the DiagramItemGroup implementation by setting
        // the items owner and calling the attachedToDiagram() hook
        // on it
        virtual bool            AddItem(
                                                        DiagramItem *item);

        // extends the DiagramItemGroup implementation by calling 
        // the detachedToDiagram() hook on the item
        virtual bool            RemoveItem(
                                                        DiagramItem *item);

public:                                 // *** operations

        // update the temporary wire to follow the mouse cursor
        void                            trackWire(
                                                        BPoint point);

        bool                            isWireTracking() const
                                                { return m_draggedWire; }

protected:                              // *** internal operations

        // do the actual background drawing
        void                            drawBackground(
                                                        BRect updateRect);

        // returns the current background color
        rgb_color                       backgroundColor() const
                                                { return m_backgroundColor; }

        // set the background color; does not refresh the display
        void                            setBackgroundColor(
                                                        rgb_color color);
        
        // set the background bitmap; does not refresh the display
        void                            setBackgroundBitmap(
                                                        BBitmap *bitmap);

        // updates the region containing the rects of all boxes in
        // the view (and thereby the "data-rect") and then adapts
        // the scrollbars if necessary
        void                            updateDataRect();

private:                                // *** internal operations

        // setup a temporary wire for "live" dragging and attaches
        // a message to the mouse
        void                            _beginWireTracking(
                                                        DiagramEndPoint *fromEndPoint);

        // delete the temporary dragged wire and invalidate display
        void                            _endWireTracking();
        
        // setups rect-tracking to additionally drag a message for
        // easier identification in MouseMoved()
        void                            _beginRectTracking(
                                                                BPoint origin);

        // takes care of actually selecting/deselecting boxes when
        // they intersect with the tracked rect
        void                            _trackRect(
                                                        BPoint origin,
                                                        BPoint current);

        // updates the scrollbars (if there are any) to represent
        // the current data-rect
        void                            _updateScrollBars();

private:                                // *** data

        // the button pressed at the last mouse event
        int32                           m_lastButton;

        // the number of clicks with the last button
        int32                           m_clickCount;

        // the point last clicked in this view
        BPoint                          m_lastClickPoint;

        // the button currently pressed (reset to 0 on mouse-up)
        // [e.moon 16nov99]
        int32                                   m_pressedButton;

        // last mouse position in screen coordinates [e.moon 16nov99]
        // only valid while m_pressedButton != 0
        BPoint                          m_lastDragPoint;

        // a pointer to the temporary wire used for wire
        // tracking
        DiagramWire                *m_draggedWire;
        
        // contains the rects of all DiagramBoxes in this view
        BRegion                         m_boxRegion;

        // contains the rect of the view actually containing something
        // (i.e. DiagramBoxes) and all free space left/above of that
        BRect                           m_dataRect;

        // true if a bitmap is used for the background; false
        // if a color is used
        bool                            m_useBackgroundBitmap;

        // the background color of the view
        rgb_color                       m_backgroundColor;
        
        // the background bitmap of the view
        BBitmap                    *m_backgroundBitmap;
};

__END_CORTEX_NAMESPACE
#endif // __DiagramView_H__