1 /* 2 * Copyright 2006, Haiku. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan Aßmus <superstippi@gmx.de> 7 */ 8 9 #include "RemoveStylesCommand.h" 10 11 #include <new> 12 #include <stdio.h> 13 14 #include "StyleContainer.h" 15 #include "Shape.h" 16 #include "Style.h" 17 18 using std::nothrow; 19 20 // constructor 21 RemoveStylesCommand::RemoveStylesCommand(StyleContainer* container, 22 Style** const styles, 23 int32 count) 24 : Command(), 25 fContainer(container), 26 fInfos(styles && count > 0 ? new (nothrow) StyleInfo[count] : NULL), 27 fCount(count), 28 fStylesRemoved(false) 29 { 30 if (!fContainer || !fInfos) 31 return; 32 33 for (int32 i = 0; i < fCount; i++) { 34 fInfos[i].style = styles[i]; 35 fInfos[i].index = fContainer->IndexOf(styles[i]); 36 if (styles[i]) { 37 int32 listenerCount = styles[i]->CountObservers(); 38 for (int32 j = 0; j < listenerCount; j++) { 39 Shape* shape = dynamic_cast<Shape*>(styles[i]->ObserverAtFast(j)); 40 if (shape) 41 fInfos[i].shapes.AddItem((void*)shape); 42 } 43 } 44 } 45 } 46 47 // destructor 48 RemoveStylesCommand::~RemoveStylesCommand() 49 { 50 if (fStylesRemoved && fInfos) { 51 for (int32 i = 0; i < fCount; i++) { 52 if (fInfos[i].style) 53 fInfos[i].style->Release(); 54 } 55 } 56 delete[] fInfos; 57 } 58 59 // InitCheck 60 status_t 61 RemoveStylesCommand::InitCheck() 62 { 63 return fContainer && fInfos ? B_OK : B_NO_INIT; 64 } 65 66 // Perform 67 status_t 68 RemoveStylesCommand::Perform() 69 { 70 // remove styles from container 71 for (int32 i = 0; i < fCount; i++) { 72 if (!fInfos[i].style) 73 continue; 74 fContainer->RemoveStyle(fInfos[i].style); 75 } 76 77 // remove styles from shapes that reference them 78 for (int32 i = 0; i < fCount; i++) { 79 if (!fInfos[i].style) 80 continue; 81 int32 shapeCount = fInfos[i].shapes.CountItems(); 82 for (int32 j = 0; j < shapeCount; j++) { 83 Shape* shape = (Shape*)fInfos[i].shapes.ItemAtFast(j); 84 shape->SetStyle(fContainer->StyleAt(0)); 85 } 86 } 87 88 fStylesRemoved = true; 89 90 return B_OK; 91 } 92 93 // Undo 94 status_t 95 RemoveStylesCommand::Undo() 96 { 97 status_t ret = B_OK; 98 99 // add styles to container and shapes which previously referenced them 100 for (int32 i = 0; i < fCount; i++) { 101 if (!fInfos[i].style) 102 continue; 103 if (!fContainer->AddStyle(fInfos[i].style, fInfos[i].index)) { 104 // roll back 105 ret = B_ERROR; 106 for (int32 j = i - 1; j >= 0; j--) { 107 fContainer->RemoveStyle(fInfos[j].style); 108 } 109 for (int32 j = i - 1; j >= 0; j--) { 110 int32 shapeCount = fInfos[j].shapes.CountItems(); 111 for (int32 k = 0; k < shapeCount; k++) { 112 Shape* shape = (Shape*)fInfos[j].shapes.ItemAtFast(k); 113 shape->SetStyle(fContainer->StyleAt(0)); 114 } 115 } 116 break; 117 } 118 int32 shapeCount = fInfos[i].shapes.CountItems(); 119 for (int32 j = 0; j < shapeCount; j++) { 120 Shape* shape = (Shape*)fInfos[i].shapes.ItemAtFast(j); 121 shape->SetStyle(fInfos[i].style); 122 } 123 } 124 125 fStylesRemoved = false; 126 127 return ret; 128 } 129 130 // GetName 131 void 132 RemoveStylesCommand::GetName(BString& name) 133 { 134 if (fCount > 1) 135 name << "Remove Styles"; 136 else 137 name << "Remove Style"; 138 } 139