<commit_before>#include "axlib.h"
#include <vector>

#define internal static
#define local_persist static
#define CGSDefaultConnection _CGSDefaultConnection()

typedef int CGSConnectionID;
extern "C" CGSConnectionID _CGSDefaultConnection(void);
extern "C" CGError CGSGetOnScreenWindowCount(const CGSConnectionID CID, CGSConnectionID TID, int *Count);
extern "C" CGError CGSGetOnScreenWindowList(const CGSConnectionID CID, CGSConnectionID TID, int Count, int *List, int *OutCount);

internal ax_state *AXState;
internal carbon_event_handler *Carbon;
internal std::map<pid_t, ax_application> *AXApplications;
internal std::map<CGDirectDisplayID, ax_display> *AXDisplays;
internal CGPoint Cursor;

internal inline AXUIElementRef
AXLibSystemWideElement()
{
    local_persist AXUIElementRef AXLibSystemWideElement;
    local_persist dispatch_once_t OnceToken;

    dispatch_once(&OnceToken, ^{
        AXLibSystemWideElement = AXUIElementCreateSystemWide();
    });

    return AXLibSystemWideElement;
}

internal CGPoint
GetCursorPos()
{
    CGEventRef Event = CGEventCreate(NULL);
    CGPoint Cursor = CGEventGetLocation(Event);
    CFRelease(Event);

    return Cursor;
}

internal bool
IsElementBelowCursor(CGRect *WindowRect)
{
    if(Cursor.x >= WindowRect->origin.x &&
       Cursor.x <= WindowRect->origin.x + WindowRect->size.width &&
       Cursor.y >= WindowRect->origin.y &&
       Cursor.y <= WindowRect->origin.y + WindowRect->size.height)
        return true;

    return false;
}

/* NOTE(koekeishiya): Does AXLib already have an ax_application struct for the given process id (?) .*/
internal bool
AXLibIsApplicationCached(pid_t PID)
{
    std::map<pid_t, ax_application>::iterator It = AXApplications->find(PID);
    return It != AXApplications->end();
}

/* NOTE(koekeishiya): Returns a pointer to the ax_application struct corresponding to the given process id. */
ax_application *AXLibGetApplicationByPID(pid_t PID)
{
    return AXLibIsApplicationCached(PID) ? &(*AXApplications)[PID] : NULL;
}

/* NOTE(koekeishiya): Returns a pointer to the ax_application struct that is the current active application. */
ax_application *AXLibGetFocusedApplication()
{
    AXUIElementRef Ref = (AXUIElementRef) AXLibGetWindowProperty(AXLibSystemWideElement(), kAXFocusedApplicationAttribute);

    if(Ref)
    {
        pid_t PID;
        AXUIElementGetPid(Ref, &PID);
        CFRelease(Ref);

        return AXLibGetApplicationByPID(PID);
    }

    return NULL;
}

/* NOTE(koekeishiya): Returns a pointer to the ax_window struct that is the current focused window of an application. */
ax_window *AXLibGetFocusedWindow(ax_application *Application)
{
    AXUIElementRef Ref = (AXUIElementRef) AXLibGetWindowProperty(Application->Ref, kAXFocusedWindowAttribute);
    if(Ref)
    {
        uint32_t WID = AXLibGetWindowID(Ref);
        CFRelease(Ref);

        ax_window *Window = AXLibFindApplicationWindow(Application, WID);
        return Window;
    }

    return NULL;
}

/* NOTE(koekeishiya): The passed ax_window will now become the focused window of OSX. If the
                      application corresponding to this window is not active, it will be activated. */
void AXLibSetFocusedWindow(ax_window *Window)
{
    if(!AXLibIsApplicationActive(Window->Application))
    {
        AXLibSetWindowProperty(Window->Ref, kAXMainAttribute, kCFBooleanTrue);
        AXLibSetWindowProperty(Window->Ref, kAXFocusedAttribute, kCFBooleanTrue);
        AXUIElementPerformAction(Window->Ref, kAXRaiseAction);

        /* NOTE(koekeishiya): If the window to gain focus is on a different display,
         * we want to ignore the window focused event emitted by OSX after the
         * application has been activated. */
        if(AXLibWindowDisplay(Window) != AXLibMainDisplay())
            AXLibAddFlags(Window->Application, AXApplication_PrepIgnoreFocus);

        SetFrontProcessWithOptions(&Window->Application->PSN, kSetFrontProcessFrontWindowOnly);
    }
    else
    {
        /* NOTE(koekeishiya): The application is already the active application,
         * and so we simply need to make this window the focused one. */
        AXLibSetWindowProperty(Window->Ref, kAXMainAttribute, kCFBooleanTrue);
    }
}

/* NOTE(koekeishiya): Returns a vector of all windows that we currently know about. This fuction is probably not necessary. */
std::vector<ax_window *> AXLibGetAllKnownWindows()
{
    std::vector<ax_window *> Windows;
    std::map<pid_t, ax_application>::iterator It;
    for(It = AXApplications->begin(); It != AXApplications->end(); ++It)
    {
        ax_application *Application = &It->second;
        std::map<uint32_t, ax_window *>::iterator WIt;
        for(WIt = Application->Windows.begin(); WIt != Application->Windows.end(); ++WIt)
            Windows.push_back(WIt->second);
    }

    return Windows;
}

internal inline bool
AXLibArrayContains(int *WindowList, int WindowCount, uint32_t WindowID)
{
    while(WindowCount > 0)
    {
        if(WindowList[--WindowCount] == WindowID)
            return true;
    }

    return false;
}

/* NOTE(koekeishiya): Returns a list of pointer to ax_window structs containing all windows currently visible,
                     filtering by their associated kAXWindowRole and kAXWindowSubrole. */
std::vector<ax_window *> AXLibGetAllVisibleWindows()
{
    std::vector<ax_window *> Windows;

    /* NOTE(koekeishiya): Is it necessary to actually decide how many windows are on the screen.
                          Can we just pass an estimated high enough number such as 200 (?) */
    int WindowCount = 0;
    CGError Error = CGSGetOnScreenWindowCount(CGSDefaultConnection, 0, &WindowCount);
    if(Error == kCGErrorSuccess)
    {
        /* NOTE(koekeishiya): This function seems to be pretty expensive.. Is CGWindowListCopyWindowInfo faster (?) */
        int WindowList[WindowCount];
        Error = CGSGetOnScreenWindowList(CGSDefaultConnection, 0, WindowCount, WindowList, &WindowCount);
        if(Error == kCGErrorSuccess)
        {
            std::map<pid_t, ax_application>::iterator It;
            for(It = AXApplications->begin(); It != AXApplications->end(); ++It)
            {
                ax_application *Application = &It->second;
                if(!AXLibIsApplicationHidden(Application))
                {
                    std::map<uint32_t, ax_window *>::iterator WIt;
                    for(WIt = Application->Windows.begin(); WIt != Application->Windows.end(); ++WIt)
                    {
                        ax_window *Window = WIt->second;
                        /* NOTE(koekeishiya): If a window is minimized, the ArrayContains check should fail
                                              if(!AXLibIsWindowMinimized(Window->Ref)) */

                        if((AXLibArrayContains(WindowList, WindowCount, Window->ID)) &&
                           (AXLibIsWindowStandard(Window) || AXLibIsWindowCustom(Window)) &&
                           (!AXLibHasFlags(Window, AXWindow_Floating)))
                        {
                            Windows.push_back(Window);
                        }
                    }
                }
            }
        }
    }

    return Windows;
}

/* NOTE(koekeishiya): Returns the window id of the window below the cursor. */
#define CONTEXT_MENU_LAYER 101
uint32_t AXLibGetWindowBelowCursor()
{
    uint32_t Result = 0;
    CGWindowListOption WindowListOption = kCGWindowListOptionOnScreenOnly |
                                          kCGWindowListExcludeDesktopElements;
    Cursor = GetCursorPos();

    CFArrayRef WindowList = CGWindowListCopyWindowInfo(WindowListOption, kCGNullWindowID);
    if(WindowList)
    {
        CFIndex WindowCount = CFArrayGetCount(WindowList);
        for(std::size_t Index = 0; Index < WindowCount; ++Index)
        {
            uint32_t WindowID;
            uint32_t WindowLayer;
            CGRect WindowRect = {};
            CFNumberRef CFWindowNumber;
            CFNumberRef CFWindowLayer;
            CFDictionaryRef CFWindowBounds;
            CFDictionaryRef Elem = (CFDictionaryRef)CFArrayGetValueAtIndex(WindowList, Index);
            CFWindowNumber = (CFNumberRef) CFDictionaryGetValue(Elem, CFSTR("kCGWindowNumber"));
            CFWindowLayer = (CFNumberRef) CFDictionaryGetValue(Elem, CFSTR("kCGWindowLayer"));
            CFWindowBounds = (CFDictionaryRef) CFDictionaryGetValue(Elem, CFSTR("kCGWindowBounds"));
            CFNumberGetValue(CFWindowNumber, kCFNumberSInt32Type, &WindowID);
            CFNumberGetValue(CFWindowLayer, kCFNumberSInt32Type, &WindowLayer);
            CFRelease(CFWindowNumber);
            CFRelease(CFWindowLayer);
            if(CFWindowBounds)
            {
                CGRectMakeWithDictionaryRepresentation(CFWindowBounds, &WindowRect);
            }

            CFStringRef CFOwner = (CFStringRef) CFDictionaryGetValue(Elem, CFSTR("kCGWindowOwnerName"));
            CFStringRef CFName = (CFStringRef) CFDictionaryGetValue(Elem, CFSTR("kCGWindowName"));

            bool IsKwmOverlay = (CFOwner && CFStringCompare(CFOwner, CFSTR("kwm-overlay"), 0) == kCFCompareEqualTo);
            bool IsDock = (CFOwner && CFStringCompare(CFOwner, CFSTR("Dock"), 0) == kCFCompareEqualTo);
            bool IsLaunchpad = (CFName && CFStringCompare(CFName, CFSTR("LPSpringboard"), 0) == kCFCompareEqualTo);
            bool IsDockBar = (CFName && CFStringCompare(CFName, CFSTR("Dock"), 0) == kCFCompareEqualTo);

            if((IsDock && IsDockBar) || (IsKwmOverlay))
                continue;

            if((IsDock&& IsLaunchpad) || (WindowLayer == CONTEXT_MENU_LAYER))
            {
                CFRelease(WindowList);
                return 0;
            }

            if(IsElementBelowCursor(&WindowRect))
            {
                Result = WindowID;
                break;
            }
        }

        CFRelease(WindowList);
    }

    return Result;
}

/* NOTE(koekeishiya): Update state of known applications and their windows, stored inside the ax_state passed to AXLibInit(..). */
void AXLibRunningApplications()
{
    std::map<pid_t, std::string> List = SharedWorkspaceRunningApplications();

    std::map<pid_t, std::string>::iterator It;
    for(It = List.begin(); It != List.end(); ++It)
    {
        pid_t PID = It->first;
        if(!AXLibIsApplicationCached(PID))
        {
            std::string Name = It->second;
            (*AXApplications)[PID] = AXLibConstructApplication(PID, Name);
            AXLibInitializeApplication(PID);
        }
        else
        {
            AXLibAddApplicationWindows(&(*AXApplications)[PID]);
        }
    }
}

/* NOTE(koekeishiya): This function is responsible for initializing internal variables used by AXLib, and must be
                      called before using any of the provided functions!  In addition to this, it will also
                      populate the display and running applications map in the ax_state struct.  */
void AXLibInit(ax_state *State)
{
    AXState = State;
    AXApplications = &AXState->Applications;
    AXDisplays = &AXState->Displays;
    Carbon = &AXState->Carbon;
    AXUIElementSetMessagingTimeout(AXLibSystemWideElement(), 1.0);
    AXLibInitializeCarbonEventHandler(Carbon, AXApplications);
    SharedWorkspaceInitialize(AXApplications);
    AXLibInitializeDisplays(AXDisplays);
    AXLibRunningApplications();
}
<commit_msg>ignore new borders<commit_after>#include "axlib.h"
#include <vector>

#define internal static
#define local_persist static
#define CGSDefaultConnection _CGSDefaultConnection()

typedef int CGSConnectionID;
extern "C" CGSConnectionID _CGSDefaultConnection(void);
extern "C" CGError CGSGetOnScreenWindowCount(const CGSConnectionID CID, CGSConnectionID TID, int *Count);
extern "C" CGError CGSGetOnScreenWindowList(const CGSConnectionID CID, CGSConnectionID TID, int Count, int *List, int *OutCount);

internal ax_state *AXState;
internal carbon_event_handler *Carbon;
internal std::map<pid_t, ax_application> *AXApplications;
internal std::map<CGDirectDisplayID, ax_display> *AXDisplays;
internal CGPoint Cursor;

internal inline AXUIElementRef
AXLibSystemWideElement()
{
    local_persist AXUIElementRef AXLibSystemWideElement;
    local_persist dispatch_once_t OnceToken;

    dispatch_once(&OnceToken, ^{
        AXLibSystemWideElement = AXUIElementCreateSystemWide();
    });

    return AXLibSystemWideElement;
}

internal CGPoint
GetCursorPos()
{
    CGEventRef Event = CGEventCreate(NULL);
    CGPoint Cursor = CGEventGetLocation(Event);
    CFRelease(Event);

    return Cursor;
}

internal bool
IsElementBelowCursor(CGRect *WindowRect)
{
    if(Cursor.x >= WindowRect->origin.x &&
       Cursor.x <= WindowRect->origin.x + WindowRect->size.width &&
       Cursor.y >= WindowRect->origin.y &&
       Cursor.y <= WindowRect->origin.y + WindowRect->size.height)
        return true;

    return false;
}

/* NOTE(koekeishiya): Does AXLib already have an ax_application struct for the given process id (?) .*/
internal bool
AXLibIsApplicationCached(pid_t PID)
{
    std::map<pid_t, ax_application>::iterator It = AXApplications->find(PID);
    return It != AXApplications->end();
}

/* NOTE(koekeishiya): Returns a pointer to the ax_application struct corresponding to the given process id. */
ax_application *AXLibGetApplicationByPID(pid_t PID)
{
    return AXLibIsApplicationCached(PID) ? &(*AXApplications)[PID] : NULL;
}

/* NOTE(koekeishiya): Returns a pointer to the ax_application struct that is the current active application. */
ax_application *AXLibGetFocusedApplication()
{
    AXUIElementRef Ref = (AXUIElementRef) AXLibGetWindowProperty(AXLibSystemWideElement(), kAXFocusedApplicationAttribute);

    if(Ref)
    {
        pid_t PID;
        AXUIElementGetPid(Ref, &PID);
        CFRelease(Ref);

        return AXLibGetApplicationByPID(PID);
    }

    return NULL;
}

/* NOTE(koekeishiya): Returns a pointer to the ax_window struct that is the current focused window of an application. */
ax_window *AXLibGetFocusedWindow(ax_application *Application)
{
    AXUIElementRef Ref = (AXUIElementRef) AXLibGetWindowProperty(Application->Ref, kAXFocusedWindowAttribute);
    if(Ref)
    {
        uint32_t WID = AXLibGetWindowID(Ref);
        CFRelease(Ref);

        ax_window *Window = AXLibFindApplicationWindow(Application, WID);
        return Window;
    }

    return NULL;
}

/* NOTE(koekeishiya): The passed ax_window will now become the focused window of OSX. If the
                      application corresponding to this window is not active, it will be activated. */
void AXLibSetFocusedWindow(ax_window *Window)
{
    if(!AXLibIsApplicationActive(Window->Application))
    {
        AXLibSetWindowProperty(Window->Ref, kAXMainAttribute, kCFBooleanTrue);
        AXLibSetWindowProperty(Window->Ref, kAXFocusedAttribute, kCFBooleanTrue);
        AXUIElementPerformAction(Window->Ref, kAXRaiseAction);

        /* NOTE(koekeishiya): If the window to gain focus is on a different display,
         * we want to ignore the window focused event emitted by OSX after the
         * application has been activated. */
        if(AXLibWindowDisplay(Window) != AXLibMainDisplay())
            AXLibAddFlags(Window->Application, AXApplication_PrepIgnoreFocus);

        SetFrontProcessWithOptions(&Window->Application->PSN, kSetFrontProcessFrontWindowOnly);
    }
    else
    {
        /* NOTE(koekeishiya): The application is already the active application,
         * and so we simply need to make this window the focused one. */
        AXLibSetWindowProperty(Window->Ref, kAXMainAttribute, kCFBooleanTrue);
    }
}

/* NOTE(koekeishiya): Returns a vector of all windows that we currently know about. This fuction is probably not necessary. */
std::vector<ax_window *> AXLibGetAllKnownWindows()
{
    std::vector<ax_window *> Windows;
    std::map<pid_t, ax_application>::iterator It;
    for(It = AXApplications->begin(); It != AXApplications->end(); ++It)
    {
        ax_application *Application = &It->second;
        std::map<uint32_t, ax_window *>::iterator WIt;
        for(WIt = Application->Windows.begin(); WIt != Application->Windows.end(); ++WIt)
            Windows.push_back(WIt->second);
    }

    return Windows;
}

internal inline bool
AXLibArrayContains(int *WindowList, int WindowCount, uint32_t WindowID)
{
    while(WindowCount > 0)
    {
        if(WindowList[--WindowCount] == WindowID)
            return true;
    }

    return false;
}

/* NOTE(koekeishiya): Returns a list of pointer to ax_window structs containing all windows currently visible,
                     filtering by their associated kAXWindowRole and kAXWindowSubrole. */
std::vector<ax_window *> AXLibGetAllVisibleWindows()
{
    std::vector<ax_window *> Windows;

    /* NOTE(koekeishiya): Is it necessary to actually decide how many windows are on the screen.
                          Can we just pass an estimated high enough number such as 200 (?) */
    int WindowCount = 0;
    CGError Error = CGSGetOnScreenWindowCount(CGSDefaultConnection, 0, &WindowCount);
    if(Error == kCGErrorSuccess)
    {
        /* NOTE(koekeishiya): This function seems to be pretty expensive.. Is CGWindowListCopyWindowInfo faster (?) */
        int WindowList[WindowCount];
        Error = CGSGetOnScreenWindowList(CGSDefaultConnection, 0, WindowCount, WindowList, &WindowCount);
        if(Error == kCGErrorSuccess)
        {
            std::map<pid_t, ax_application>::iterator It;
            for(It = AXApplications->begin(); It != AXApplications->end(); ++It)
            {
                ax_application *Application = &It->second;
                if(!AXLibIsApplicationHidden(Application))
                {
                    std::map<uint32_t, ax_window *>::iterator WIt;
                    for(WIt = Application->Windows.begin(); WIt != Application->Windows.end(); ++WIt)
                    {
                        ax_window *Window = WIt->second;
                        /* NOTE(koekeishiya): If a window is minimized, the ArrayContains check should fail
                                              if(!AXLibIsWindowMinimized(Window->Ref)) */

                        if((AXLibArrayContains(WindowList, WindowCount, Window->ID)) &&
                           (AXLibIsWindowStandard(Window) || AXLibIsWindowCustom(Window)) &&
                           (!AXLibHasFlags(Window, AXWindow_Floating)))
                        {
                            Windows.push_back(Window);
                        }
                    }
                }
            }
        }
    }

    return Windows;
}

/* NOTE(koekeishiya): Returns the window id of the window below the cursor. */
#define CONTEXT_MENU_LAYER 101
uint32_t AXLibGetWindowBelowCursor()
{
    uint32_t Result = 0;
    CGWindowListOption WindowListOption = kCGWindowListOptionOnScreenOnly |
                                          kCGWindowListExcludeDesktopElements;
    Cursor = GetCursorPos();

    CFArrayRef WindowList = CGWindowListCopyWindowInfo(WindowListOption, kCGNullWindowID);
    if(WindowList)
    {
        CFIndex WindowCount = CFArrayGetCount(WindowList);
        for(std::size_t Index = 0; Index < WindowCount; ++Index)
        {
            uint32_t WindowID;
            uint32_t WindowLayer;
            CGRect WindowRect = {};
            CFNumberRef CFWindowNumber;
            CFNumberRef CFWindowLayer;
            CFDictionaryRef CFWindowBounds;
            CFDictionaryRef Elem = (CFDictionaryRef)CFArrayGetValueAtIndex(WindowList, Index);
            CFWindowNumber = (CFNumberRef) CFDictionaryGetValue(Elem, CFSTR("kCGWindowNumber"));
            CFWindowLayer = (CFNumberRef) CFDictionaryGetValue(Elem, CFSTR("kCGWindowLayer"));
            CFWindowBounds = (CFDictionaryRef) CFDictionaryGetValue(Elem, CFSTR("kCGWindowBounds"));
            CFNumberGetValue(CFWindowNumber, kCFNumberSInt32Type, &WindowID);
            CFNumberGetValue(CFWindowLayer, kCFNumberSInt32Type, &WindowLayer);
            CFRelease(CFWindowNumber);
            CFRelease(CFWindowLayer);
            if(CFWindowBounds)
            {
                CGRectMakeWithDictionaryRepresentation(CFWindowBounds, &WindowRect);
            }

            CFStringRef CFOwner = (CFStringRef) CFDictionaryGetValue(Elem, CFSTR("kCGWindowOwnerName"));
            CFStringRef CFName = (CFStringRef) CFDictionaryGetValue(Elem, CFSTR("kCGWindowName"));

            bool IsKwmOverlay = (CFOwner && CFStringCompare(CFOwner, CFSTR("kwm"), 0) == kCFCompareEqualTo);
            bool IsDock = (CFOwner && CFStringCompare(CFOwner, CFSTR("Dock"), 0) == kCFCompareEqualTo);
            bool IsLaunchpad = (CFName && CFStringCompare(CFName, CFSTR("LPSpringboard"), 0) == kCFCompareEqualTo);
            bool IsDockBar = (CFName && CFStringCompare(CFName, CFSTR("Dock"), 0) == kCFCompareEqualTo);

            if((IsDock && IsDockBar) || (IsKwmOverlay))
                continue;

            if((IsDock&& IsLaunchpad) || (WindowLayer == CONTEXT_MENU_LAYER))
            {
                CFRelease(WindowList);
                return 0;
            }

            if(IsElementBelowCursor(&WindowRect))
            {
                Result = WindowID;
                break;
            }
        }

        CFRelease(WindowList);
    }

    return Result;
}

/* NOTE(koekeishiya): Update state of known applications and their windows, stored inside the ax_state passed to AXLibInit(..). */
void AXLibRunningApplications()
{
    std::map<pid_t, std::string> List = SharedWorkspaceRunningApplications();

    std::map<pid_t, std::string>::iterator It;
    for(It = List.begin(); It != List.end(); ++It)
    {
        pid_t PID = It->first;
        if(!AXLibIsApplicationCached(PID))
        {
            std::string Name = It->second;
            (*AXApplications)[PID] = AXLibConstructApplication(PID, Name);
            AXLibInitializeApplication(PID);
        }
        else
        {
            AXLibAddApplicationWindows(&(*AXApplications)[PID]);
        }
    }
}

/* NOTE(koekeishiya): This function is responsible for initializing internal variables used by AXLib, and must be
                      called before using any of the provided functions!  In addition to this, it will also
                      populate the display and running applications map in the ax_state struct.  */
void AXLibInit(ax_state *State)
{
    AXState = State;
    AXApplications = &AXState->Applications;
    AXDisplays = &AXState->Displays;
    Carbon = &AXState->Carbon;
    AXUIElementSetMessagingTimeout(AXLibSystemWideElement(), 1.0);
    AXLibInitializeCarbonEventHandler(Carbon, AXApplications);
    SharedWorkspaceInitialize(AXApplications);
    AXLibInitializeDisplays(AXDisplays);
    AXLibRunningApplications();
}
<|endoftext|>


<commit_before>/** \copyright
 * Copyright (c) 2013, Stuart W Baker
 * 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.
 *
 * 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 HOLDER 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.
 *
 * \file SysMap.hxx
 * This file provides a C++ abstraction of BSD sys/tree.h.
 *
 * @author Stuart W. Baker
 * @date 2 December 2013
 */

#ifndef _UTILS_SYSMAP_HXX_
#define _UTILS_SYSMAP_HXX_

#include <sys/tree.hxx>
#include <cstdint>

#include "utils/macros.h"

/** This is an abstraction of BSD sys/tree.h that is meant to mimic the
 * semantics of std::map without having to link in libstdc++.
 */
template <typename Key, typename Value> class SysMap
{
public:
    /** Default Constructor which with no mapping entry limit.
     */
    SysMap()
        : entries(0),
          used(0),
          freeList(NULL),
          nodes(NULL)

    {
        clear();
    }

    /** Constructor that limits the number of mappings to a static pool.
     * @param entries number of nodes to statically create and track
     */
    SysMap(size_t entries)
        : entries(entries),
          used(0),
          freeList(NULL),
          nodes(new Node[entries])
    {
        HASSERT(entries != 0);
        clear();
    }

    /** Destructor.
     */
    ~SysMap()
    {
        delete nodes;
    }

    /** mimic std::pair */
    struct Pair
    {
        Key first; /**< mimic first element in an std::pair */
        Value second; /**< mimic second element in an std::pair */
    };

private:
    /** The metadata for a tree node. */
    struct Node
    {
    public:
        RB_ENTRY(Node) entry;
        union
        {
            Pair p; /**< pair of element */
            struct
            {
                Key key; /**< key by which to sort the node */
                Value value; /**< value of the node */
            };
        };

        /** Default constructor.  Does not initialize key or value.
         */
        Node()
        {
        }
    };

public:
    /** This mimics an std::iterator.
     */
    class Iterator
    {
    public:
        /** Default constructor.
         */
        Iterator()
            : node(NULL),
              m(NULL)
        {
        }

        /** Copy constructor.
         */
        Iterator(const Iterator &it)
            : node(it.node),
              m(it.m)
        {
        }

        /** Constructor.
         * @param context context passed in at instantiation
         * @param node node to initialize this iteration with
         */
        Iterator(SysMap* context, Node *node)
            : node(node),
              m(context)

        {
        }

        /** Destructor */
        ~Iterator()
        {
        }

        /** Overloaded reference operator.
         */
        Pair &operator*() const
        {
            return node->p;
        }

        /** Overloaded pointer operator.
         */
        Pair *operator->() const
        {
            return &node->p;
        }

        /** Overloaded pre-increement operator. */
        Iterator &operator ++ ()
        {
            if (node)
            {
                node = RB_NEXT(m->tree, &(m->head), node);
            }
            return *this;
        }

        /** Overloaded not equals operator. */
        bool operator != (const Iterator &it)
        {
            return node != it.node;
        }

        /** Overloaded equals operator. */
        bool operator == (const Iterator &it)
        {
            return node == it.node;
        }

    private:
        /** node this iteration is currently indexed to */
        Node *node;

        /** Context this iteration lives in */
        SysMap *m;

        /** Allow access to node member */
        friend class SysMap;
    };

    /** Find the index associated with the key and create it if does not exist.
     * @param key key to lookup
     * @return value of the key by reference
     */
    Value &operator[](const Key &key)
    {
        Iterator it = find(key);
        if (it == end())
        {
            Node *node = alloc();
            HASSERT(node);
            node->key = key;
            node->value = (Value)0;
            HASSERT(RB_INSERT(tree, &head, node) == NULL);
            it = Iterator(this, node);
        }
        return (*it).second;
    }

    /** Number of elements currently in the map.
     * @return number of elements in the map
     */
    size_t size()
    {
        return used;
    }

    /** Maximum theoretical number of elements in the map.
     * @return maximum theoretical number of elements in the map
     */
    size_t max_size()
    {
        return entries ? entries : UINTPTR_MAX / sizeof(Pair);
    }

    /** Removes all elements in the map. */
    void clear()
    {
        RB_INIT(&head);
        used = 0;
        if (entries)
        {
            nodes->entry.rbe_left = NULL;

            for (size_t i = 1; i < entries; ++i)
            {
                nodes[i].entry.rbe_left = nodes + (i - 1);
            }
            freeList = nodes + (entries - 1);
        }
    }

    /** Find an element matching the given key.
     * @param key key to search for
     * @return iterator index pointing to key, else iterator end() if not found
     */
    Iterator find(const Key &key)
    {
        Node lookup;
        lookup.key = key;
        Node *node = RB_FIND(tree, &head, &lookup);

        return node ? Iterator(this, node) : Iterator();
    }

    /** Get an iterator index pointing one past the last element in mapping.
     * @return iterator index pointing to one past the last element in mapping
     */
    Iterator end()
    {
        return Iterator();
    }

    /** Get an iterator index pointing to the first element in the mapping.
     * @return iterator index pointing to the first element in the mapping or
     * to end() if the mapping is empty
     */
    Iterator begin()
    {
        Node *node = RB_MIN(tree, &head);

        return node ? Iterator(this, node) : Iterator();
    }

    /** Remove a node from the tree.
     * @param key key for the element to remove
     * @return number of elements removed
     */
    size_t erase(Key key)
    {
        Node lookup;
        lookup.key = key;
        Node *node = RB_FIND(tree, &head, &lookup);

        if (node)
        {
            RB_REMOVE(tree, &head, node);
            free(node);
            return 1;
        }
        return 0;
    }

    /** Remove a node from the tree.
     * @param it iterator index for the element to remove
     */
    void erase(Iterator it)
    {
        Node *node = it.node;
        if (node)
        {
            RB_REMOVE(tree, &head, node);
            free(node);
        }
    }

private:
    /** Allocate a node from the free list.
     * @return newly allocated node, else NULL if no free nodes left
     */
    Node *alloc()
    {
        if (nodes)
        {
            if (freeList != NULL)
            {
                Node *node = freeList;
                freeList = freeList->entry.rbe_left;
                memset(node, 0, sizeof(Node));
                ++used;
                return node;
            }
            return NULL;
        }
        else
        {
            Node *node = new Node;
            memset(node, 0, sizeof(Node));
            ++used;
            return node;
        }

    }

    /** free a node to the free list if it exists.
     * @param node node to free
     */
    void free(Node *node)
    {
        if (nodes)
        {
            node->entry.rbe_left = freeList;
            freeList = node;
            --used;
        }
        else
        {
            --used;
            delete node;
        }
    }

    /** Compare two nodes.  They type is the largest signed type we know.  This
     * is because sys/tree.h only works with signed results on a compare.
     * @param a first of two nodes to compare
     * @param b second of two nodes to compare
     * @return difference between node keys (a->key - b->key)
     */
    int64_t compare(Node *a, Node *b)
    {
        union comp
        {
            int64_t s;
            Key     k;
        };

        comp ca, cb;
        ca.s = 0;
        cb.s = 0;
        ca.k = a->key;
        cb.k = b->key;

        return ca.s - cb.s;
    }

    /** total number of entries for this instance */
    size_t entries;

    /** total number of entries in use for this instance */
    size_t used;

    /** list of free nodes */
    Node *freeList;

    /** location of pre-allocated Node memory */
    Node *nodes;

    /** The datagram tree type. */
    RB_HEAD(tree, Node);

    /** The datagram tree methods. */
    RB_GENERATE(tree, Node, entry, compare);

    /** tree instance */
    struct tree head;

    DISALLOW_COPY_AND_ASSIGN(SysMap);
};

#endif /* _UTILS_SYSMAP_HXX_ */
<commit_msg>Enables SysMap to have 0 (unlimited) as entry count even if the limited-entries consturctor is used. This is helpful as there are cases where a linker symbol decides the capacity of the map, and it would be nice to set that linker symbol to 0.<commit_after>/** \copyright
 * Copyright (c) 2013, Stuart W Baker
 * 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.
 *
 * 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 HOLDER 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.
 *
 * \file SysMap.hxx
 * This file provides a C++ abstraction of BSD sys/tree.h.
 *
 * @author Stuart W. Baker
 * @date 2 December 2013
 */

#ifndef _UTILS_SYSMAP_HXX_
#define _UTILS_SYSMAP_HXX_

#include <sys/tree.hxx>
#include <cstdint>

#include "utils/macros.h"

/** This is an abstraction of BSD sys/tree.h that is meant to mimic the
 * semantics of std::map without having to link in libstdc++.
 */
template <typename Key, typename Value> class SysMap
{
public:
    /** Default Constructor which with no mapping entry limit.
     */
    SysMap()
        : entries(0),
          used(0),
          freeList(NULL),
          nodes(NULL)

    {
        clear();
    }

    /** Constructor that limits the number of mappings to a static pool.
     * @param entries number of nodes to statically create and track
     */
    SysMap(size_t entries)
        : entries(entries),
          used(0),
          freeList(NULL),
          nodes(NULL)
    {
        if (entries) {
            nodes = new Node[entries];
        }
        clear();
    }

    /** Destructor.
     */
    ~SysMap()
    {
        delete nodes;
    }

    /** mimic std::pair */
    struct Pair
    {
        Key first; /**< mimic first element in an std::pair */
        Value second; /**< mimic second element in an std::pair */
    };

private:
    /** The metadata for a tree node. */
    struct Node
    {
    public:
        RB_ENTRY(Node) entry;
        union
        {
            Pair p; /**< pair of element */
            struct
            {
                Key key; /**< key by which to sort the node */
                Value value; /**< value of the node */
            };
        };

        /** Default constructor.  Does not initialize key or value.
         */
        Node()
        {
        }
    };

public:
    /** This mimics an std::iterator.
     */
    class Iterator
    {
    public:
        /** Default constructor.
         */
        Iterator()
            : node(NULL),
              m(NULL)
        {
        }

        /** Copy constructor.
         */
        Iterator(const Iterator &it)
            : node(it.node),
              m(it.m)
        {
        }

        /** Constructor.
         * @param context context passed in at instantiation
         * @param node node to initialize this iteration with
         */
        Iterator(SysMap* context, Node *node)
            : node(node),
              m(context)

        {
        }

        /** Destructor */
        ~Iterator()
        {
        }

        /** Overloaded reference operator.
         */
        Pair &operator*() const
        {
            return node->p;
        }

        /** Overloaded pointer operator.
         */
        Pair *operator->() const
        {
            return &node->p;
        }

        /** Overloaded pre-increement operator. */
        Iterator &operator ++ ()
        {
            if (node)
            {
                node = RB_NEXT(m->tree, &(m->head), node);
            }
            return *this;
        }

        /** Overloaded not equals operator. */
        bool operator != (const Iterator &it)
        {
            return node != it.node;
        }

        /** Overloaded equals operator. */
        bool operator == (const Iterator &it)
        {
            return node == it.node;
        }

    private:
        /** node this iteration is currently indexed to */
        Node *node;

        /** Context this iteration lives in */
        SysMap *m;

        /** Allow access to node member */
        friend class SysMap;
    };

    /** Find the index associated with the key and create it if does not exist.
     * @param key key to lookup
     * @return value of the key by reference
     */
    Value &operator[](const Key &key)
    {
        Iterator it = find(key);
        if (it == end())
        {
            Node *node = alloc();
            HASSERT(node);
            node->key = key;
            node->value = (Value)0;
            HASSERT(RB_INSERT(tree, &head, node) == NULL);
            it = Iterator(this, node);
        }
        return (*it).second;
    }

    /** Number of elements currently in the map.
     * @return number of elements in the map
     */
    size_t size()
    {
        return used;
    }

    /** Maximum theoretical number of elements in the map.
     * @return maximum theoretical number of elements in the map
     */
    size_t max_size()
    {
        return entries ? entries : UINTPTR_MAX / sizeof(Pair);
    }

    /** Removes all elements in the map. */
    void clear()
    {
        RB_INIT(&head);
        used = 0;
        if (entries)
        {
            nodes->entry.rbe_left = NULL;

            for (size_t i = 1; i < entries; ++i)
            {
                nodes[i].entry.rbe_left = nodes + (i - 1);
            }
            freeList = nodes + (entries - 1);
        }
    }

    /** Find an element matching the given key.
     * @param key key to search for
     * @return iterator index pointing to key, else iterator end() if not found
     */
    Iterator find(const Key &key)
    {
        Node lookup;
        lookup.key = key;
        Node *node = RB_FIND(tree, &head, &lookup);

        return node ? Iterator(this, node) : Iterator();
    }

    /** Get an iterator index pointing one past the last element in mapping.
     * @return iterator index pointing to one past the last element in mapping
     */
    Iterator end()
    {
        return Iterator();
    }

    /** Get an iterator index pointing to the first element in the mapping.
     * @return iterator index pointing to the first element in the mapping or
     * to end() if the mapping is empty
     */
    Iterator begin()
    {
        Node *node = RB_MIN(tree, &head);

        return node ? Iterator(this, node) : Iterator();
    }

    /** Remove a node from the tree.
     * @param key key for the element to remove
     * @return number of elements removed
     */
    size_t erase(Key key)
    {
        Node lookup;
        lookup.key = key;
        Node *node = RB_FIND(tree, &head, &lookup);

        if (node)
        {
            RB_REMOVE(tree, &head, node);
            free(node);
            return 1;
        }
        return 0;
    }

    /** Remove a node from the tree.
     * @param it iterator index for the element to remove
     */
    void erase(Iterator it)
    {
        Node *node = it.node;
        if (node)
        {
            RB_REMOVE(tree, &head, node);
            free(node);
        }
    }

private:
    /** Allocate a node from the free list.
     * @return newly allocated node, else NULL if no free nodes left
     */
    Node *alloc()
    {
        if (nodes)
        {
            if (freeList != NULL)
            {
                Node *node = freeList;
                freeList = freeList->entry.rbe_left;
                memset(node, 0, sizeof(Node));
                ++used;
                return node;
            }
            return NULL;
        }
        else
        {
            Node *node = new Node;
            memset(node, 0, sizeof(Node));
            ++used;
            return node;
        }

    }

    /** free a node to the free list if it exists.
     * @param node node to free
     */
    void free(Node *node)
    {
        if (nodes)
        {
            node->entry.rbe_left = freeList;
            freeList = node;
            --used;
        }
        else
        {
            --used;
            delete node;
        }
    }

    /** Compare two nodes.  They type is the largest signed type we know.  This
     * is because sys/tree.h only works with signed results on a compare.
     * @param a first of two nodes to compare
     * @param b second of two nodes to compare
     * @return difference between node keys (a->key - b->key)
     */
    int64_t compare(Node *a, Node *b)
    {
        union comp
        {
            int64_t s;
            Key     k;
        };

        comp ca, cb;
        ca.s = 0;
        cb.s = 0;
        ca.k = a->key;
        cb.k = b->key;

        return ca.s - cb.s;
    }

    /** total number of entries for this instance */
    size_t entries;

    /** total number of entries in use for this instance */
    size_t used;

    /** list of free nodes */
    Node *freeList;

    /** location of pre-allocated Node memory */
    Node *nodes;

    /** The datagram tree type. */
    RB_HEAD(tree, Node);

    /** The datagram tree methods. */
    RB_GENERATE(tree, Node, entry, compare);

    /** tree instance */
    struct tree head;

    DISALLOW_COPY_AND_ASSIGN(SysMap);
};

#endif /* _UTILS_SYSMAP_HXX_ */
<|endoftext|>


<commit_before>/*
 * Copyright 2014 Helge Bahmann <hcb@chaoticmind.net>
 * See COPYING for terms of redistribution.
 */

#include "test-registry.hpp"

#include <assert.h>
#include <jive/util/intrusive-hash.hpp>

struct my_item {
	int key;
	int value;
	struct {
		my_item * prev;
		my_item * next;
	} hash_chain;
};

struct my_accessor {
	int get_key(const my_item * item) const noexcept { return item->key; }
	my_item * get_prev(const my_item * item) const noexcept { return item->hash_chain.prev; }
	my_item * get_next(const my_item * item) const noexcept { return item->hash_chain.next; }
	void set_prev(my_item * item, my_item * prev) const noexcept { item->hash_chain.prev = prev; }
	void set_next(my_item * item, my_item * next) const noexcept { item->hash_chain.next = next; }
};

typedef jive::detail::intrusive_hash<
	int,
	my_item,
	my_accessor> my_hash;

struct my_stritem {
	std::string key;
	std::string value;
	jive::detail::intrusive_hash_anchor<my_stritem> hash_chain;

	typedef jive::detail::intrusive_hash_accessor<
		std::string, my_stritem,
		&my_stritem::key, &my_stritem::hash_chain> hash_accessor;
};

typedef jive::detail::intrusive_hash<
	std::string,
	my_stritem,
	my_stritem::hash_accessor> my_strhash;

static void test_int_hash(void)
{
	my_hash m;

	assert(m.find(42) == m.end());

	my_item i1 = {42, 0};
	m.insert(&i1);
	assert(&*m.find(42) == &i1);

	my_item i2 = {10, 0};
	m.insert(&i2);

	m.erase(&i1);
	assert(m.find(42) == m.end());
	m.insert(&i1);
	assert(&*m.find(42) == &i1);

	int seen_i1 = 0, seen_i2 = 0;
	for (const my_item & i : m) {
		assert((&i == &i1) || (&i == &i2));
		if (&i == &i1) {
			++ seen_i1;
		}
		if (&i == &i2) {
			++ seen_i2;
		}
	}
	assert(seen_i1 == 1);
	assert(seen_i2 == 1);
}

static void test_str_hash(void)
{
	my_strhash m;

	assert(m.find("42") == m.end());

	my_stritem i1 = {"42", "0"};
	m.insert(&i1);
	assert(&*m.find("42") == &i1);

	my_stritem i2 = {"10", "0"};
	m.insert(&i2);

	m.erase(&i1);
	assert(m.find("42") == m.end());
	m.insert(&i1);
	assert(&*m.find("42") == &i1);

	int seen_i1 = 0, seen_i2 = 0;
	for (const my_stritem & i : m) {
		assert((&i == &i1) || (&i == &i2));
		if (&i == &i1) {
			++ seen_i1;
		}
		if (&i == &i2) {
			++ seen_i2;
		}
	}
	assert(seen_i1 == 1);
	assert(seen_i2 == 1);
}

static int test_main(void)
{
	test_int_hash();
	test_str_hash();

	return 0;
}

JIVE_UNIT_TEST_REGISTER("util/test-intrusive-hash", test_main)
<commit_msg>tests: ensure compilation without warnings<commit_after>/*
 * Copyright 2014 Helge Bahmann <hcb@chaoticmind.net>
 * See COPYING for terms of redistribution.
 */

#include "test-registry.hpp"

#include <assert.h>
#include <jive/util/intrusive-hash.hpp>

struct my_item {
	my_item(int k, int v)
	: key(k)
	, value(v)
	{
		hash_chain.prev = hash_chain.next = nullptr;
	}

	int key;
	int value;
	struct {
		my_item * prev;
		my_item * next;
	} hash_chain;
};

struct my_accessor {
	int get_key(const my_item * item) const noexcept { return item->key; }
	my_item * get_prev(const my_item * item) const noexcept { return item->hash_chain.prev; }
	my_item * get_next(const my_item * item) const noexcept { return item->hash_chain.next; }
	void set_prev(my_item * item, my_item * prev) const noexcept { item->hash_chain.prev = prev; }
	void set_next(my_item * item, my_item * next) const noexcept { item->hash_chain.next = next; }
};

typedef jive::detail::intrusive_hash<
	int,
	my_item,
	my_accessor> my_hash;

struct my_stritem {
	my_stritem(
		const std::string & k
	, const std::string & v)
	: key(k)
	, value(v)
	{}

	std::string key;
	std::string value;
	jive::detail::intrusive_hash_anchor<my_stritem> hash_chain;

	typedef jive::detail::intrusive_hash_accessor<
		std::string, my_stritem,
		&my_stritem::key, &my_stritem::hash_chain> hash_accessor;
};

typedef jive::detail::intrusive_hash<
	std::string,
	my_stritem,
	my_stritem::hash_accessor> my_strhash;

static void test_int_hash(void)
{
	my_hash m;

	assert(m.find(42) == m.end());

	my_item i1 = {42, 0};
	m.insert(&i1);
	assert(&*m.find(42) == &i1);

	my_item i2 = {10, 0};
	m.insert(&i2);

	m.erase(&i1);
	assert(m.find(42) == m.end());
	m.insert(&i1);
	assert(&*m.find(42) == &i1);

	int seen_i1 = 0, seen_i2 = 0;
	for (const my_item & i : m) {
		assert((&i == &i1) || (&i == &i2));
		if (&i == &i1) {
			++ seen_i1;
		}
		if (&i == &i2) {
			++ seen_i2;
		}
	}
	assert(seen_i1 == 1);
	assert(seen_i2 == 1);
}

static void test_str_hash(void)
{
	my_strhash m;

	assert(m.find("42") == m.end());

	my_stritem i1 = {"42", "0"};
	m.insert(&i1);
	assert(&*m.find("42") == &i1);

	my_stritem i2 = {"10", "0"};
	m.insert(&i2);

	m.erase(&i1);
	assert(m.find("42") == m.end());
	m.insert(&i1);
	assert(&*m.find("42") == &i1);

	int seen_i1 = 0, seen_i2 = 0;
	for (const my_stritem & i : m) {
		assert((&i == &i1) || (&i == &i2));
		if (&i == &i1) {
			++ seen_i1;
		}
		if (&i == &i2) {
			++ seen_i2;
		}
	}
	assert(seen_i1 == 1);
	assert(seen_i2 == 1);
}

static int test_main(void)
{
	test_int_hash();
	test_str_hash();

	return 0;
}

JIVE_UNIT_TEST_REGISTER("util/test-intrusive-hash", test_main)
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: extrusioncontrols.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: kz $ $Date: 2005-01-21 14:27:00 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _SVX_EXTRUSION_CONTROLS_HXX
#define _SVX_EXTRUSION_CONTROLS_HXX

#ifndef _VALUESET_HXX //autogen
#include <svtools/valueset.hxx>
#endif
#ifndef _SFXLSTNER_HXX //autogen
#include <svtools/lstner.hxx>
#endif
#ifndef _SFXTBXCTRL_HXX //autogen
#include <sfx2/tbxctrl.hxx>
#endif
#ifndef _SVTREEBOX_HXX
#include <svtools/svtreebx.hxx>
#endif
#ifndef _SV_BUTTON_HXX
#include <vcl/button.hxx>
#endif
#ifndef _SV_DIALOG_HXX
#include <vcl/dialog.hxx>
#endif
#ifndef _SV_FIELD_HXX
#include <vcl/field.hxx>
#endif

#ifndef _COM_SUN_STAR_FRAME_XFRAME_HPP_
#include <com/sun/star/frame/XFrame.hpp>
#endif

#ifndef INCLUDED_SVXDLLAPI_H
#include "svx/svxdllapi.h"
#endif

class SfxBindings;
class ToolbarMenu;
class SfxStatusForwarder;
class SvxTbxButtonColorUpdater_Impl;

//========================================================================

namespace svx
{

class ExtrusionDirectionWindow : public SfxPopupWindow
{
private:
    ToolbarMenu*        mpMenu;
    ValueSet*           mpDirectionSet;
    ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > mxFrame;

    SfxStatusForwarder* mpDirectionForewarder;
    SfxStatusForwarder* mpProjectionForewarder;

    Image       maImgDirection[9];
    Image       maImgDirectionH[9];

    Image       maImgPerspective;
    Image       maImgPerspectiveH;
    Image       maImgParallel;
    Image       maImgParallelH;

    bool        mbPopupMode;

    DECL_LINK( SelectHdl, void * );
    void            FillValueSet();

    void implSetDirection( sal_Int32 nSkew, bool bEnabled = true );
    void implSetProjection( sal_Int32 nProjection, bool bEnabled = true );

protected:
    virtual BOOL    Close();
    virtual void    PopupModeEnd();

    /** This function is called when the window gets the focus.  It grabs
        the focus to the line ends value set so that it can be controlled with
        the keyboard.
    */
    virtual void GetFocus (void);

public:
    ExtrusionDirectionWindow( USHORT nId,
                              const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame );
    ~ExtrusionDirectionWindow();

    void            StartSelection();

    virtual SfxPopupWindow* Clone() const;

    virtual void StateChanged( USHORT nSID, SfxItemState eState, const SfxPoolItem* pState );
    virtual void DataChanged( const DataChangedEvent& rDCEvt );
};

//========================================================================

class SVX_DLLPUBLIC ExtrusionDirectionControl : public SfxToolBoxControl
{
public:
    SFX_DECL_TOOLBOX_CONTROL();
    ExtrusionDirectionControl( USHORT nSlotId, USHORT nId, ToolBox& rTbx );
    ~ExtrusionDirectionControl();

    virtual void                StateChanged( USHORT nSID, SfxItemState eState,
                                              const SfxPoolItem* pState );
    virtual SfxPopupWindowType  GetPopupWindowType() const;
    virtual SfxPopupWindow*     CreatePopupWindow();
};

//========================================================================

class ExtrusionDepthWindow : public SfxPopupWindow
{
private:
    ToolbarMenu* mpMenu;

    Image maImgDepth0;
    Image maImgDepth1;
    Image maImgDepth2;
    Image maImgDepth3;
    Image maImgDepth4;
    Image maImgDepthInfinity;

    Image maImgDepth0h;
    Image maImgDepth1h;
    Image maImgDepth2h;
    Image maImgDepth3h;
    Image maImgDepth4h;
    Image maImgDepthInfinityh;

    SfxStatusForwarder* mpDepthForewarder;
    SfxStatusForwarder* mpMetricForewarder;
    ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > mxFrame;

    bool        mbPopupMode;
    FieldUnit   meUnit;
    double      mfDepth;
    bool        mbEnabled;
    bool        mbInExecute;

    DECL_LINK( SelectHdl, void * );

    void    implFillStrings( FieldUnit eUnit );
    void    implSetDepth( double fDepth, bool bEnabled );

protected:
    virtual BOOL    Close();
    virtual void    PopupModeEnd();

    /** This function is called when the window gets the focus.  It grabs
        the focus to the line ends value set so that it can be controlled with
        the keyboard.
    */
    virtual void GetFocus (void);

public:
    ExtrusionDepthWindow( USHORT nId,
                          const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame );
    ~ExtrusionDepthWindow();

    void            StartSelection();

    virtual SfxPopupWindow* Clone() const;

    virtual void StateChanged( USHORT nSID, SfxItemState eState, const SfxPoolItem* pState );
    virtual void DataChanged( const DataChangedEvent& rDCEvt );
};

//========================================================================

class SVX_DLLPUBLIC ExtrusionDepthControl : public SfxToolBoxControl
{
public:
    SFX_DECL_TOOLBOX_CONTROL();
    ExtrusionDepthControl( USHORT nSlotId, USHORT nId, ToolBox& rTbx );
    ~ExtrusionDepthControl();

    virtual void                StateChanged( USHORT nSID, SfxItemState eState,
                                              const SfxPoolItem* pState );
    virtual SfxPopupWindowType  GetPopupWindowType() const;
    virtual SfxPopupWindow*     CreatePopupWindow();
};

//========================================================================

class ExtrusionLightingWindow : public SfxPopupWindow
{
private:
    ToolbarMenu* mpMenu;
    ValueSet*    mpLightingSet;

    Image maImgLightingOff[9];
    Image maImgLightingOn[9];
    Image maImgLightingPreview[9];

    Image maImgLightingOffh[9];
    Image maImgLightingOnh[9];
    Image maImgLightingPreviewh[9];

    Image maImgBright;
    Image maImgNormal;
    Image maImgDim;
    Image maImgBrighth;
    Image maImgNormalh;
    Image maImgDimh;

    SfxStatusForwarder* mpLightingDirectionForewarder;
    SfxStatusForwarder* mpLightingIntensityForewarder;
    ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > mxFrame;

    bool    mbPopupMode;
    int     mnLevel;
    bool    mbLevelEnabled;
    int     mnDirection;
    bool    mbDirectionEnabled;

    void    implSetIntensity( int nLevel, bool bEnabled );
    void    implSetDirection( int nDirection, bool bEnabled );

    DECL_LINK( SelectHdl, void * );

protected:
    virtual BOOL    Close();
    virtual void    PopupModeEnd();

    /** This function is called when the window gets the focus.  It grabs
        the focus to the line ends value set so that it can be controlled with
        the keyboard.
    */
    virtual void GetFocus (void);

public:
    ExtrusionLightingWindow( USHORT nId,
                             const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame );
    ~ExtrusionLightingWindow();

    void            StartSelection();

    virtual SfxPopupWindow* Clone() const;

    virtual void StateChanged( USHORT nSID, SfxItemState eState, const SfxPoolItem* pState );
    virtual void DataChanged( const DataChangedEvent& rDCEvt );
};

//========================================================================

class SVX_DLLPUBLIC ExtrusionLightingControl : public SfxToolBoxControl
{
public:
    SFX_DECL_TOOLBOX_CONTROL();
    ExtrusionLightingControl( USHORT nSlotid, USHORT nId, ToolBox& rTbx );
    ~ExtrusionLightingControl();

    virtual void                StateChanged( USHORT nSID, SfxItemState eState,
                                              const SfxPoolItem* pState );
    virtual SfxPopupWindowType  GetPopupWindowType() const;
    virtual SfxPopupWindow*     CreatePopupWindow();
};

//========================================================================

class ExtrusionSurfaceWindow : public SfxPopupWindow
{
private:
    ToolbarMenu* mpMenu;

    Image maImgSurface1;
    Image maImgSurface2;
    Image maImgSurface3;
    Image maImgSurface4;
    Image maImgSurface1h;
    Image maImgSurface2h;
    Image maImgSurface3h;
    Image maImgSurface4h;

    SfxStatusForwarder* mpSurfaceForewarder;
    ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > mxFrame;

    bool        mbPopupMode;

    DECL_LINK( SelectHdl, void * );

    void    implSetSurface( int nSurface, bool bEnabled );

protected:
    virtual BOOL    Close();
    virtual void    PopupModeEnd();

    /** This function is called when the window gets the focus.  It grabs
        the focus to the line ends value set so that it can be controlled with
        the keyboard.
    */
    virtual void GetFocus (void);

public:
    ExtrusionSurfaceWindow( USHORT nId,
                            const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame );
    ~ExtrusionSurfaceWindow();

    void            StartSelection();

    virtual SfxPopupWindow* Clone() const;

    virtual void StateChanged( USHORT nSID, SfxItemState eState, const SfxPoolItem* pState );
    virtual void DataChanged( const DataChangedEvent& rDCEvt );
};

//========================================================================

class SVX_DLLPUBLIC ExtrusionSurfaceControl : public SfxToolBoxControl
{
public:
    SFX_DECL_TOOLBOX_CONTROL();
    ExtrusionSurfaceControl( USHORT nSlotId, USHORT nId, ToolBox& rTbx );
    ~ExtrusionSurfaceControl();

    virtual void                StateChanged( USHORT nSID, SfxItemState eState,
                                              const SfxPoolItem* pState );
    virtual SfxPopupWindowType  GetPopupWindowType() const;
    virtual SfxPopupWindow*     CreatePopupWindow();
};

//========================================================================

class SVX_DLLPUBLIC ExtrusionColorControl : public SfxToolBoxControl
{
private:
    SvxTbxButtonColorUpdater_Impl*  mpBtnUpdater;

public:
    SFX_DECL_TOOLBOX_CONTROL();
    ExtrusionColorControl( USHORT nSlotId, USHORT nId, ToolBox& rTbx );
    ~ExtrusionColorControl();

    virtual void                StateChanged( USHORT nSID, SfxItemState eState,
                                              const SfxPoolItem* pState );
    virtual SfxPopupWindowType  GetPopupWindowType() const;
    virtual SfxPopupWindow*     CreatePopupWindow();
};

//========================================================================

class ExtrusionDepthDialog : public ModalDialog
{
    FixedText           maFLDepth;
    MetricField         maMtrDepth;
    OKButton            maOKButton;
    CancelButton        maCancelButton;
    HelpButton          maHelpButton;

    FieldUnit           meDefaultUnit;

public:
    ExtrusionDepthDialog( Window* pParent, double fDepth, FieldUnit eDefaultUnit );
    ~ExtrusionDepthDialog();

    double getDepth() const;
};

}
#endif

<commit_msg>INTEGRATION: CWS fwk14 (1.4.276); FILE MERGED 2005/05/31 12:57:42 cd 1.4.276.1: #i46092# Use correct parent for floating windows<commit_after>/*************************************************************************
 *
 *  $RCSfile: extrusioncontrols.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: obo $ $Date: 2005-07-08 09:24:20 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _SVX_EXTRUSION_CONTROLS_HXX
#define _SVX_EXTRUSION_CONTROLS_HXX

#ifndef _VALUESET_HXX //autogen
#include <svtools/valueset.hxx>
#endif
#ifndef _SFXLSTNER_HXX //autogen
#include <svtools/lstner.hxx>
#endif
#ifndef _SFXTBXCTRL_HXX //autogen
#include <sfx2/tbxctrl.hxx>
#endif
#ifndef _SVTREEBOX_HXX
#include <svtools/svtreebx.hxx>
#endif
#ifndef _SV_BUTTON_HXX
#include <vcl/button.hxx>
#endif
#ifndef _SV_DIALOG_HXX
#include <vcl/dialog.hxx>
#endif
#ifndef _SV_FIELD_HXX
#include <vcl/field.hxx>
#endif

#ifndef _COM_SUN_STAR_FRAME_XFRAME_HPP_
#include <com/sun/star/frame/XFrame.hpp>
#endif

#ifndef INCLUDED_SVXDLLAPI_H
#include "svx/svxdllapi.h"
#endif

class SfxBindings;
class ToolbarMenu;
class SfxStatusForwarder;
class SvxTbxButtonColorUpdater_Impl;

//========================================================================

namespace svx
{

class ExtrusionDirectionWindow : public SfxPopupWindow
{
private:
    ToolbarMenu*        mpMenu;
    ValueSet*           mpDirectionSet;
    ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > mxFrame;

    SfxStatusForwarder* mpDirectionForewarder;
    SfxStatusForwarder* mpProjectionForewarder;

    Image       maImgDirection[9];
    Image       maImgDirectionH[9];

    Image       maImgPerspective;
    Image       maImgPerspectiveH;
    Image       maImgParallel;
    Image       maImgParallelH;

    bool        mbPopupMode;

    DECL_LINK( SelectHdl, void * );
    void            FillValueSet();

    void implSetDirection( sal_Int32 nSkew, bool bEnabled = true );
    void implSetProjection( sal_Int32 nProjection, bool bEnabled = true );
    void implInit();

protected:
    virtual BOOL    Close();
    virtual void    PopupModeEnd();

    /** This function is called when the window gets the focus.  It grabs
        the focus to the line ends value set so that it can be controlled with
        the keyboard.
    */
    virtual void GetFocus (void);

public:
    ExtrusionDirectionWindow( USHORT nId,
                              const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame );
    ExtrusionDirectionWindow( USHORT nId,
                              const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame,
                              Window* pParentWindow );
    ~ExtrusionDirectionWindow();

    void            StartSelection();

    virtual SfxPopupWindow* Clone() const;

    virtual void StateChanged( USHORT nSID, SfxItemState eState, const SfxPoolItem* pState );
    virtual void DataChanged( const DataChangedEvent& rDCEvt );
};

//========================================================================

class SVX_DLLPUBLIC ExtrusionDirectionControl : public SfxToolBoxControl
{
public:
    SFX_DECL_TOOLBOX_CONTROL();
    ExtrusionDirectionControl( USHORT nSlotId, USHORT nId, ToolBox& rTbx );
    ~ExtrusionDirectionControl();

    virtual void                StateChanged( USHORT nSID, SfxItemState eState,
                                              const SfxPoolItem* pState );
    virtual SfxPopupWindowType  GetPopupWindowType() const;
    virtual SfxPopupWindow*     CreatePopupWindow();
};

//========================================================================

class ExtrusionDepthWindow : public SfxPopupWindow
{
private:
    ToolbarMenu* mpMenu;

    Image maImgDepth0;
    Image maImgDepth1;
    Image maImgDepth2;
    Image maImgDepth3;
    Image maImgDepth4;
    Image maImgDepthInfinity;

    Image maImgDepth0h;
    Image maImgDepth1h;
    Image maImgDepth2h;
    Image maImgDepth3h;
    Image maImgDepth4h;
    Image maImgDepthInfinityh;

    SfxStatusForwarder* mpDepthForewarder;
    SfxStatusForwarder* mpMetricForewarder;
    ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > mxFrame;

    bool        mbPopupMode;
    FieldUnit   meUnit;
    double      mfDepth;
    bool        mbEnabled;
    bool        mbInExecute;

    DECL_LINK( SelectHdl, void * );

    void    implFillStrings( FieldUnit eUnit );
    void    implSetDepth( double fDepth, bool bEnabled );
    void    implInit();

protected:
    virtual BOOL    Close();
    virtual void    PopupModeEnd();

    /** This function is called when the window gets the focus.  It grabs
        the focus to the line ends value set so that it can be controlled with
        the keyboard.
    */
    virtual void GetFocus (void);

public:
    ExtrusionDepthWindow( USHORT nId,
                          const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame );
    ExtrusionDepthWindow( USHORT nId,
                          const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame,
                          Window* pParentWindow );
    ~ExtrusionDepthWindow();

    void            StartSelection();

    virtual SfxPopupWindow* Clone() const;

    virtual void StateChanged( USHORT nSID, SfxItemState eState, const SfxPoolItem* pState );
    virtual void DataChanged( const DataChangedEvent& rDCEvt );
};

//========================================================================

class SVX_DLLPUBLIC ExtrusionDepthControl : public SfxToolBoxControl
{
public:
    SFX_DECL_TOOLBOX_CONTROL();
    ExtrusionDepthControl( USHORT nSlotId, USHORT nId, ToolBox& rTbx );
    ~ExtrusionDepthControl();

    virtual void                StateChanged( USHORT nSID, SfxItemState eState,
                                              const SfxPoolItem* pState );
    virtual SfxPopupWindowType  GetPopupWindowType() const;
    virtual SfxPopupWindow*     CreatePopupWindow();
};

//========================================================================

class ExtrusionLightingWindow : public SfxPopupWindow
{
private:
    ToolbarMenu* mpMenu;
    ValueSet*    mpLightingSet;

    Image maImgLightingOff[9];
    Image maImgLightingOn[9];
    Image maImgLightingPreview[9];

    Image maImgLightingOffh[9];
    Image maImgLightingOnh[9];
    Image maImgLightingPreviewh[9];

    Image maImgBright;
    Image maImgNormal;
    Image maImgDim;
    Image maImgBrighth;
    Image maImgNormalh;
    Image maImgDimh;

    SfxStatusForwarder* mpLightingDirectionForewarder;
    SfxStatusForwarder* mpLightingIntensityForewarder;
    ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > mxFrame;

    bool    mbPopupMode;
    int     mnLevel;
    bool    mbLevelEnabled;
    int     mnDirection;
    bool    mbDirectionEnabled;

    void    implSetIntensity( int nLevel, bool bEnabled );
    void    implSetDirection( int nDirection, bool bEnabled );
    void    implInit();

    DECL_LINK( SelectHdl, void * );

protected:
    virtual BOOL    Close();
    virtual void    PopupModeEnd();

    /** This function is called when the window gets the focus.  It grabs
        the focus to the line ends value set so that it can be controlled with
        the keyboard.
    */
    virtual void GetFocus (void);

public:
    ExtrusionLightingWindow( USHORT nId,
                             const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame );
    ExtrusionLightingWindow( USHORT nId,
                             const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame,
                             Window* pParentWindow );
    ~ExtrusionLightingWindow();

    void            StartSelection();

    virtual SfxPopupWindow* Clone() const;

    virtual void StateChanged( USHORT nSID, SfxItemState eState, const SfxPoolItem* pState );
    virtual void DataChanged( const DataChangedEvent& rDCEvt );
};

//========================================================================

class SVX_DLLPUBLIC ExtrusionLightingControl : public SfxToolBoxControl
{
public:
    SFX_DECL_TOOLBOX_CONTROL();
    ExtrusionLightingControl( USHORT nSlotid, USHORT nId, ToolBox& rTbx );
    ~ExtrusionLightingControl();

    virtual void                StateChanged( USHORT nSID, SfxItemState eState,
                                              const SfxPoolItem* pState );
    virtual SfxPopupWindowType  GetPopupWindowType() const;
    virtual SfxPopupWindow*     CreatePopupWindow();
};

//========================================================================

class ExtrusionSurfaceWindow : public SfxPopupWindow
{
private:
    ToolbarMenu* mpMenu;

    Image maImgSurface1;
    Image maImgSurface2;
    Image maImgSurface3;
    Image maImgSurface4;
    Image maImgSurface1h;
    Image maImgSurface2h;
    Image maImgSurface3h;
    Image maImgSurface4h;

    SfxStatusForwarder* mpSurfaceForewarder;
    ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > mxFrame;

    bool        mbPopupMode;

    DECL_LINK( SelectHdl, void * );

    void    implSetSurface( int nSurface, bool bEnabled );
    void    implInit();

protected:
    virtual BOOL    Close();
    virtual void    PopupModeEnd();

    /** This function is called when the window gets the focus.  It grabs
        the focus to the line ends value set so that it can be controlled with
        the keyboard.
    */
    virtual void GetFocus (void);

public:
    ExtrusionSurfaceWindow( USHORT nId,
                            const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame );
    ExtrusionSurfaceWindow( USHORT nId,
                            const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame,
                            Window* pParentWindow );
    ~ExtrusionSurfaceWindow();

    void            StartSelection();

    virtual SfxPopupWindow* Clone() const;

    virtual void StateChanged( USHORT nSID, SfxItemState eState, const SfxPoolItem* pState );
    virtual void DataChanged( const DataChangedEvent& rDCEvt );
};

//========================================================================

class SVX_DLLPUBLIC ExtrusionSurfaceControl : public SfxToolBoxControl
{
public:
    SFX_DECL_TOOLBOX_CONTROL();
    ExtrusionSurfaceControl( USHORT nSlotId, USHORT nId, ToolBox& rTbx );
    ~ExtrusionSurfaceControl();

    virtual void                StateChanged( USHORT nSID, SfxItemState eState,
                                              const SfxPoolItem* pState );
    virtual SfxPopupWindowType  GetPopupWindowType() const;
    virtual SfxPopupWindow*     CreatePopupWindow();
};

//========================================================================

class SVX_DLLPUBLIC ExtrusionColorControl : public SfxToolBoxControl
{
private:
    SvxTbxButtonColorUpdater_Impl*  mpBtnUpdater;

public:
    SFX_DECL_TOOLBOX_CONTROL();
    ExtrusionColorControl( USHORT nSlotId, USHORT nId, ToolBox& rTbx );
    ~ExtrusionColorControl();

    virtual void                StateChanged( USHORT nSID, SfxItemState eState,
                                              const SfxPoolItem* pState );
    virtual SfxPopupWindowType  GetPopupWindowType() const;
    virtual SfxPopupWindow*     CreatePopupWindow();
};

//========================================================================

class ExtrusionDepthDialog : public ModalDialog
{
    FixedText           maFLDepth;
    MetricField         maMtrDepth;
    OKButton            maOKButton;
    CancelButton        maCancelButton;
    HelpButton          maHelpButton;

    FieldUnit           meDefaultUnit;

public:
    ExtrusionDepthDialog( Window* pParent, double fDepth, FieldUnit eDefaultUnit );
    ~ExtrusionDepthDialog();

    double getDepth() const;
};

}
#endif

<|endoftext|>