#include #include #include #include "display.h" #include "CPstring.h" #include "tree.h" // constants static const int WINDOW_HEIGHT = 320; // height of samba window static const int WINDOW_WIDTH = 900; // width of samba wndow static const int MAX_Y = 100; // Maximum y coordinate in samba static const int MAX_X = 900; // Maximum x coordinate in samba static const int RECT_HEIGHT = 10; // Height of node in tree static const int RECT_WIDTH = 50; // width of node in tree static const int LINE_WIDTH = 1; // width of a line static const int LEVEL_HEIGHT = (RECT_HEIGHT + 5); //Height of a level static const int LEVEL_WIDTH = (RECT_WIDTH + 5); //width of a node // in a level const int Display::DELAY_TIME = 300; //How long to stall // Prefixes for samba static const string RECT_STRING = "rect"; // for rectangles static const string TEXT_STRING = "text"; // for text static const string SET_ID = "set"; // for sets static int ourDisplayCount = 0; // # of display obuects made Display::Display(ostream & OutputStream, displayColor defaultColor) : myOutputStream(OutputStream), myMaxLevel(0), myLowLevelMaxNodes(1), myDefaultColor(defaultColor), myID(ourDisplayCount) // postcondition: all fields initizlied { ourDisplayCount ++; myOutputStream.precision(1); // show one decimal point for myOutputStream.setf(ios::fixed); // all numbers myOutputStream.setf(ios::showpoint); // initialize coordinates in samba myOutputStream << "viewdef Tree_" << myID << " " << WINDOW_WIDTH << " " << WINDOW_HEIGHT << endl; myOutputStream << "coords " << 0<< " " << 0 << " " << MAX_X << " " << MAX_Y << endl; } void Display::InitializeTreeNode(TreeNode * node) // postcondition: Node draw with line to parent (if not root node) { if (node) { // compute Position of node double x = ComputeXPosition (node->level, node->id); double y = ComputeYPosition (node->level); // Draw Box myOutputStream << "rectangle " << RECT_STRING << node->info << " " << x << " " << y << " " << RECT_WIDTH << " " << RECT_HEIGHT << " " << GetNodeColor(myDefaultColor) << " outline" << endl; // Draw Text double xText = x + RECT_WIDTH/2; double yText = y + RECT_HEIGHT/2; myOutputStream << "text " << TEXT_STRING << node->info << " " << xText << " " << yText << " 1 " << " " << GetNodeColor(myDefaultColor) << " " << node->info << endl; // Make them a set so samba can manipulate whole set myOutputStream << "set " << SET_ID << node->info << " 2 " << RECT_STRING << node->info << " " << TEXT_STRING << node->info << " " << endl; // Draw line to parent ConnectNodeToParent(node); } } void Display::DeleteNode(TreeNode * node) // post condition: Node is deleted from samba { if (node) { // Delete set myOutputStream << "delete " << SET_ID << node->info << endl; // Delete Box myOutputStream << "delete " << RECT_STRING << node->info << endl; // Delete Text myOutputStream << "delete " << TEXT_STRING << node->info << endl; } } void Display::MoveNode(TreeNode * node) // postcondition: node moved on screen { if (node) { SetNodeColor(node, red); // compute Position of node double x = ComputeXPosition (node->level, node->id); double y = ComputeYPosition (node->level); // Move Node myOutputStream << "move " << SET_ID << node->info << " " << x+RECT_WIDTH/2 << " " << y+RECT_HEIGHT/2 << " " << endl; SetNodeDefaultColor(node); } } void Display::ConnectNodeToParent(TreeNode * node) // postcondition: Line drawn from node to its parent { if (node && node->level>0) { DrawLine(node->level-1, node->id/2, node->level, node->id); } } void Display::DisconnectNodeFromParent(TreeNode * node) // postcondition: Line between node and its parent deleted { if (node && node->level>0) { DeleteLine(node->level-1, node->id/2, node->level, node->id); } } void Display::DeleteLine(int fromLevel, int fromID, int toLevel, int toID) // postcondition: line deleted { myOutputStream << "delete " << fromLevel << "_" << fromID << "_" << toLevel << "_" << toID << endl; } void Display::DrawLine(int fromLevel, int fromID, int toLevel, int toID) // postcondition: line drawn { double x1 = ComputeXPosition (fromLevel, fromID) + RECT_WIDTH/2; double y1 = ComputeYPosition (fromLevel); double x2 = ComputeXPosition (toLevel, toID) + RECT_WIDTH/2; double y2 = ComputeYPosition (toLevel) + RECT_HEIGHT; myOutputStream << "pointline " << fromLevel << "_" << fromID << "_" << toLevel << "_" << toID << " " << x1 << " " << y1 << " " << x2 << " " << y2 << " " << GetNodeColor(myDefaultColor) << " thin" << endl; } void Display::UpdateLevelCount(int maxLevel) // postcondition: Updates Maximum level of a tree and # of nodes in // that level { myMaxLevel = maxLevel; myLowLevelMaxNodes = pow(2, myMaxLevel); } void Display::FlashNode(TreeNode * node) // postcondition: node changes color waits and turns back to old color { if (node) { SetNodeColor(node, red); Stall(); SetNodeDefaultColor(node); } } void Display::Stall(int delay) // postcondition: Sends a stall command to samba { myOutputStream << "delay " << delay << endl; } void Display::SetNodeColor(TreeNode * node, displayColor color) // postcondition: sets the node's color to input value { myOutputStream << "color " << SET_ID << node->info << " " << GetNodeColor(color) << endl; } string Display::GetNodeColor(displayColor color) // postcondition: returns samba string for color { // color table static const char * colorTable[] = {"black", "red", "blue", "orange", "yellow", "green", "cyan"}; return colorTable[color]; } void Display::SetNodeDefaultColor(TreeNode * node) // postcondtion: sets node's color to the default color { SetNodeColor(node, myDefaultColor); } double Display::ComputeXPosition(int level, int id) // postcondition: returns x positon for Node with given level and id # { double xPos; // return value if (level==myMaxLevel) { double max_id = myLowLevelMaxNodes; double ctr_id = max_id/2 - 0.5; xPos = (MAX_X/2) + (id - ctr_id) * LEVEL_WIDTH - RECT_WIDTH/2; } else { double multFactor = pow(2,myMaxLevel-level); int minIndex = (int)(multFactor * id); int maxIndex = (int)(minIndex + multFactor - 1); double xMin = ComputeXPosition(myMaxLevel, minIndex); double xMax = ComputeXPosition(myMaxLevel, maxIndex); xPos = (xMin + xMax) / 2.; } return xPos; } double Display::ComputeYPosition(int level) // postcondtion: returns y position for object at given level of tree { double yPos = MAX_Y - (level * LEVEL_HEIGHT) - RECT_HEIGHT; return yPos; }