Windows2003-3790/windows/advcore/gdiplus/test/gdiptest/gdipclip.h
2020-09-30 16:53:55 +02:00

498 lines
9.0 KiB
C++

enum NodeType
{
DataNode = 0,
AndNode = 1,
OrNode = 2,
XorNode = 3
};
// shape flags for temporary editing
#define ShapeDisabled 0x00000001
template <class Data> class TreeNode
{
public:
friend class TestShapeRegion;
TreeNode(NodeType type = DataNode, Data* data = NULL, BOOL notNode = FALSE)
{
this->type = type;
this->data = data;
this->notNode = notNode;
nodeName = NULL;
if (data)
{
// !! violates we are a template class.. Yipes!! hacky!!
path = new GraphicsPath();
data->AddToPath(path);
}
else
path = NULL;
nextSibling = NULL;
prevSibling = NULL;
parent = NULL;
firstChild = NULL;
hItem = (HTREEITEM)-1;
}
~TreeNode()
{
if (nodeName)
free(nodeName);
TreeNode* next = firstChild;
while (next)
{
TreeNode* nextnext = next->nextSibling;
delete next;
next = nextnext;
}
if (nextSibling)
nextSibling->prevSibling = prevSibling;
if (prevSibling)
prevSibling->nextSibling = nextSibling;
if (parent && parent->firstChild == this)
parent->firstChild = nextSibling;
if (path)
delete path;
};
TreeNode* GetRoot()
{
TreeNode* next = parent;
while (next && next->parent)
next = next->parent;
return next ? next : this;
}
BOOL HasChildren()
{
return (firstChild) ? TRUE : FALSE;
}
TreeNode* GetParent()
{
return parent;
}
TreeNode* GetNextSibling()
{
return nextSibling;
}
TreeNode* GetPrevSibling()
{
return prevSibling;
}
TreeNode* GetFirstChild()
{
return firstChild;
}
VOID MoveChildrenToParent()
{
ASSERT(parent);
TreeNode* lastSibling = parent->firstChild;
while (lastSibling->nextSibling)
lastSibling = lastSibling->nextSibling;
lastSibling->nextSibling = firstChild;
if (firstChild)
firstChild->prevSibling = lastSibling;
lastSibling = firstChild;
while (lastSibling)
{
lastSibling->parent = parent;
lastSibling = lastSibling->nextSibling;
}
firstChild = NULL;
}
HTREEITEM CreateTreeView(HWND hwndTV)
{
HTREEITEM hTreeItem = AddToTreeView(hwndTV);
if (nextSibling)
nextSibling->CreateTreeView(hwndTV);
if (firstChild)
firstChild->CreateTreeView(hwndTV);
return hTreeItem;
}
HTREEITEM AddToTreeView(HWND hwndTV)
{
nodeName = GetNodeName(type, notNode, data);
TVINSERTSTRUCT insertStruct =
{
parent ? (HTREEITEM)parent->GetHTREEITEM() : TVI_ROOT,
prevSibling ? (HTREEITEM)prevSibling->GetHTREEITEM() : TVI_FIRST,
};
TVITEMEX itemex =
{
TVIF_CHILDREN|
TVIF_PARAM|
TVIF_STATE|
TVIF_TEXT, // mask
(HTREEITEM)(NULL), // identifies TV item
0, // state
0, // stateMask
nodeName, // text to display
0, // cchTextMax
0, // iImage
0, // iSelectedImage
(firstChild ? 1 : 0), // cChildren
(LPARAM)(this), // lParam
1 // iIntegral
};
// !! wasn't able to compile into one assignment !?!?
insertStruct.itemex = itemex;
hItem = TreeView_InsertItem(hwndTV, &insertStruct);
return hItem;
};
VOID AddChild(TreeNode* node)
{
if (!firstChild)
{
firstChild = node;
node->parent = this;
node->prevSibling = NULL;
node->nextSibling = NULL;
node->firstChild = NULL;
}
else
{
TreeNode* next = firstChild;
while (next->nextSibling)
next = next->nextSibling;
next->nextSibling = node;
node->parent = this;
node->prevSibling = next;
node->nextSibling = NULL;
node->firstChild = NULL;
}
};
VOID AddSibling(TreeNode* node)
{
TreeNode* next = this;
while (next->nextSibling)
next = next->nextSibling;
if (next)
{
next->nextSibling = node;
node->parent = this->parent;
node->prevSibling = next;
node->nextSibling = NULL;
node->firstChild = NULL;
}
else
ASSERT(FALSE);
};
VOID AddAsParent(TreeNode* newParent)
{
newParent->parent = parent;
newParent->prevSibling = prevSibling;
newParent->nextSibling = nextSibling;
newParent->firstChild = this;
if (parent && parent->firstChild == this)
parent->firstChild = newParent;
if (prevSibling)
prevSibling->nextSibling = newParent;
if (nextSibling)
nextSibling->prevSibling = newParent;
nextSibling = NULL;
prevSibling = NULL;
parent = newParent;
}
BOOL IsEmpty()
{
return (type == DataNode) && (notNode) && (data == NULL);
}
BOOL IsInfinite()
{
return (type == DataNode) && (!notNode) && (data == NULL);
}
HTREEITEM GetHTREEITEM()
{
return hItem;
}
static LPTSTR GetNodeName(NodeType type,
BOOL notNode,
Data* data)
{
TCHAR tmpName[MAX_PATH];
LPTSTR name;
switch(type)
{
case DataNode:
// !! won't work on other template class types.
if (data)
{
if (notNode)
{
name = &tmpName[0];
_stprintf(&tmpName[0],
_T("NOT %s"),
data->GetShapeName());
}
else
name = data->GetShapeName();
}
else
{
if (notNode)
name = _T("Empty");
else
name = _T("Infinite");
}
break;
case AndNode:
if (notNode)
name = _T("NAND");
else
name = _T("AND");
break;
case OrNode:
if (notNode)
name = _T("NOR");
else
name = _T("OR");
break;
case XorNode:
if (notNode)
name = _T("NXOR");
else
name = _T("XOR");
break;
default:
ASSERT(FALSE);
return _T("Unknown!?!");
};
return _tcsdup(name);
}
Region* GetRegion()
{
Region* newRegion = NULL;
switch(type)
{
case DataNode:
{
if (path)
newRegion = new Region(path);
else
{
newRegion = new Region();
newRegion->SetInfinite();
}
break;
}
case AndNode:
case OrNode:
case XorNode:
{
Region* curRegion;
TreeNode* curNode = firstChild;
newRegion = new Region();
if (type == AndNode)
newRegion->SetInfinite();
else
newRegion->SetEmpty();
while (curNode)
{
curRegion = curNode->GetRegion();
if (type == AndNode)
newRegion->And(curRegion);
else if (type == OrNode)
newRegion->Or(curRegion);
else
{
ASSERT(type == XorNode);
newRegion->Xor(curRegion);
}
curNode = curNode->nextSibling;
delete curRegion;
}
break;
}
default:
ASSERT(FALSE);
break;
}
// complement the current region
if (notNode)
{
Region *tmpRegion = new Region();
tmpRegion->SetInfinite();
newRegion->Complement(tmpRegion);
delete tmpRegion;
}
return newRegion;
}
TreeNode* Clone()
{
TreeNode* newNode = new TreeNode(type, data, notNode);
TreeNode* curNode = firstChild;
TreeNode* newSibling = NULL;
// loop through all children, clone and add to 'newNode'
while (curNode)
{
TreeNode *newChild = curNode->Clone();
newChild->nodeName = GetNodeName(type, notNode, data);
if (!newSibling)
newSibling = newNode->firstChild = newChild;
else
{
newSibling->nextSibling = newChild;
newChild->prevSibling = newSibling;
newSibling = newChild;
}
newChild->parent = newNode;
curNode = curNode->nextSibling;
}
return newNode;
}
private:
NodeType type;
BOOL notNode;
LPTSTR nodeName;
TreeNode* nextSibling;
TreeNode* prevSibling;
TreeNode* firstChild;
TreeNode* parent;
HTREEITEM hItem;
GraphicsPath* path; // GDI+ path for shape
Data* data;
};
typedef TreeNode<TestShape> ClipTree;
class TestShapeRegion : public TestConfigureInterface,
public TestDialogInterface
{
public:
TestShapeRegion()
{
clipTree = new ClipTree(AndNode, NULL, FALSE);
origTree = NULL;
shapeStack = new ShapeStack();
origStack = NULL;
}
~TestShapeRegion()
{
delete clipTree;
delete shapeStack;
// do not delete 'origTree' or 'origStack'
// these are temporary references for saving under 'OK'
}
// configuration management
virtual BOOL ChangeSettings(HWND hwnd);
virtual VOID Initialize();
virtual VOID Initialize(ShapeStack* stack, TestShape* current, BOOL useClip);
// dialog control interface methods
virtual VOID InitDialog(HWND hwnd);
virtual BOOL SaveValues(HWND hwnd);
virtual BOOL ProcessDialog(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
Region* GetClipRegion();
BOOL GetClipBool()
{
return origUseClip;
}
protected:
VOID AddClipNode(HWND hwnd, NodeType type = DataNode);
VOID RemoveClipNode(HWND hwnd);
VOID ToggleNotNode(HWND hwnd);
VOID ShiftCurrentShape(HWND hwnd, INT dir);
VOID ToggleDisableShape(HWND hwnd);
VOID UpdateShapePicture(HWND hwnd);
VOID CleanUpPictures(HWND hwnd);
private:
// currently modified parameters
ShapeStack* shapeStack;
ClipTree* clipTree;
// original saved parameters
ShapeStack* origStack;
ClipTree* origTree;
BOOL origUseClip;
};