1 /* 2 * Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "AttributeWindow.h" 8 #include "ProbeView.h" 9 #include "TypeEditors.h" 10 11 #include <MenuBar.h> 12 #include <MenuItem.h> 13 #include <TabView.h> 14 #include <StringView.h> 15 #include <Alert.h> 16 #include <Directory.h> 17 #include <Volume.h> 18 19 20 static const uint32 kMsgRemoveAttribute = 'rmat'; 21 22 23 class EditorTabView : public BTabView { 24 public: 25 EditorTabView(BRect frame, const char *name, button_width width = B_WIDTH_AS_USUAL, 26 uint32 resizingMode = B_FOLLOW_ALL, uint32 flags = B_WILL_DRAW | B_FRAME_EVENTS); 27 28 virtual void FrameResized(float width, float height); 29 virtual void Select(int32 tab); 30 31 void AddRawEditorTab(BView *view); 32 void SetTypeEditorTab(BView *view); 33 34 private: 35 BView *fRawEditorView; 36 BView *fTypeEditorView; 37 BStringView *fNoEditorView; 38 int32 fRawTab; 39 }; 40 41 42 //----------------- 43 44 45 EditorTabView::EditorTabView(BRect frame, const char *name, button_width width, 46 uint32 resizingMode, uint32 flags) 47 : BTabView(frame, name, width, resizingMode, flags), 48 fRawEditorView(NULL), 49 fRawTab(-1) 50 { 51 ContainerView()->MoveBy(-ContainerView()->Frame().left, 52 TabHeight() + 1 - ContainerView()->Frame().top); 53 fNoEditorView = new BStringView(ContainerView()->Bounds(), "Type Editor", 54 "No type editor available", B_FOLLOW_NONE); 55 fNoEditorView->ResizeToPreferred(); 56 fNoEditorView->SetAlignment(B_ALIGN_CENTER); 57 fTypeEditorView = fNoEditorView; 58 59 FrameResized(0, 0); 60 61 SetTypeEditorTab(NULL); 62 } 63 64 65 void 66 EditorTabView::FrameResized(float width, float height) 67 { 68 BRect rect = Bounds(); 69 rect.top = ContainerView()->Frame().top; 70 71 ContainerView()->ResizeTo(rect.Width(), rect.Height()); 72 73 BView *view = fTypeEditorView; 74 if (view == NULL) 75 view = fNoEditorView; 76 77 BPoint point = view->Frame().LeftTop(); 78 if ((view->ResizingMode() & B_FOLLOW_RIGHT) == 0) 79 point.x = (rect.Width() - view->Bounds().Width()) / 2; 80 if ((view->ResizingMode() & B_FOLLOW_BOTTOM) == 0) 81 point.y = (rect.Height() - view->Bounds().Height()) / 2; 82 83 view->MoveTo(point); 84 } 85 86 87 void 88 EditorTabView::Select(int32 tab) 89 { 90 if (tab != fRawTab && fRawEditorView != NULL && !fRawEditorView->IsHidden(fRawEditorView)) 91 fRawEditorView->Hide(); 92 93 BTabView::Select(tab); 94 95 BView *view; 96 if (tab == fRawTab && fRawEditorView != NULL) { 97 if (fRawEditorView->IsHidden(fRawEditorView)) 98 fRawEditorView->Show(); 99 view = fRawEditorView; 100 } else 101 view = ViewForTab(Selection()); 102 103 if (view != NULL && (view->ResizingMode() & (B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM)) != 0) { 104 BRect rect = ContainerView()->Bounds(); 105 106 BRect frame = view->Frame(); 107 rect.left = frame.left; 108 rect.top = frame.top; 109 if ((view->ResizingMode() & B_FOLLOW_RIGHT) == 0) 110 rect.right = frame.right; 111 if ((view->ResizingMode() & B_FOLLOW_BOTTOM) == 0) 112 rect.bottom = frame.bottom; 113 114 view->ResizeTo(rect.Width(), rect.Height()); 115 } 116 } 117 118 119 void 120 EditorTabView::AddRawEditorTab(BView *view) 121 { 122 fRawEditorView = view; 123 if (view != NULL) 124 ContainerView()->AddChild(view); 125 126 fRawTab = CountTabs(); 127 128 view = new BView(BRect(0, 0, 5, 5), "Raw Editor", B_FOLLOW_NONE, 0); 129 view->SetViewColor(ViewColor()); 130 AddTab(view); 131 } 132 133 134 void 135 EditorTabView::SetTypeEditorTab(BView *view) 136 { 137 if (fTypeEditorView == view) 138 return; 139 140 BTab *tab = TabAt(0); 141 if (tab != NULL) 142 tab->SetView(NULL); 143 144 fTypeEditorView = view; 145 146 if (view == NULL) 147 view = fNoEditorView; 148 149 if (CountTabs() == 0) 150 AddTab(view); 151 else 152 tab->SetView(view); 153 154 FrameResized(0, 0); 155 156 #ifdef HAIKU_TARGET_PLATFORM_BEOS 157 if (Window() != NULL) { 158 // With R5's BTabView, calling select without being 159 // attached to a window crashes... 160 Select(0); 161 } 162 #else 163 Select(0); 164 #endif 165 } 166 167 168 // #pragma mark - 169 170 171 AttributeWindow::AttributeWindow(BRect _rect, entry_ref *ref, const char *attribute, 172 const BMessage *settings) 173 : ProbeWindow(_rect, ref), 174 fAttribute(strdup(attribute)) 175 { 176 // Set alternative window title for devices 177 178 char name[B_FILE_NAME_LENGTH]; 179 #ifdef HAIKU_TARGET_PLATFORM_BEOS 180 strncpy(name, ref->name, sizeof(name)); 181 name[sizeof(name) - 1] = '\0'; 182 #else 183 strlcpy(name, ref->name, sizeof(name)); 184 #endif 185 186 BEntry entry(ref); 187 if (entry.IsDirectory()) { 188 BDirectory directory(&entry); 189 if (directory.InitCheck() == B_OK && directory.IsRootDirectory()) { 190 // use the volume name for root directories 191 BVolume volume; 192 if (directory.GetVolume(&volume) == B_OK) 193 volume.GetName(name); 194 } 195 } 196 char buffer[B_PATH_NAME_LENGTH]; 197 snprintf(buffer, sizeof(buffer), "%s: %s", name, attribute); 198 SetTitle(buffer); 199 200 // add the menu 201 202 BMenuBar *menuBar = new BMenuBar(BRect(0, 0, 0, 0), NULL); 203 AddChild(menuBar); 204 205 BMenu *menu = new BMenu("Attribute"); 206 207 // the ProbeView save menu items will be inserted here 208 menu->AddItem(new BMenuItem("Remove from File", new BMessage(kMsgRemoveAttribute))); 209 menu->AddSeparatorItem(); 210 211 // the ProbeView print menu items will be inserted here 212 menu->AddSeparatorItem(); 213 214 menu->AddItem(new BMenuItem("Close", new BMessage(B_CLOSE_REQUESTED), 'W', B_COMMAND_KEY)); 215 menu->SetTargetForItems(this); 216 menuBar->AddItem(menu); 217 218 // add our interface widgets 219 220 BRect rect = Bounds(); 221 rect.top = menuBar->Bounds().Height() + 1; 222 223 BView *view = new BView(rect, "main", B_FOLLOW_ALL, 0); 224 view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 225 AddChild(view); 226 227 rect = view->Bounds(); 228 rect.top += 3; 229 230 EditorTabView *tabView = new EditorTabView(rect, "tabView"); 231 232 rect = tabView->ContainerView()->Bounds(); 233 rect.top += 3; 234 fProbeView = new ProbeView(rect, ref, attribute, settings); 235 tabView->AddRawEditorTab(fProbeView); 236 237 view->AddChild(tabView); 238 239 fTypeEditorView = GetTypeEditorFor(rect, fProbeView->Editor()); 240 if (fTypeEditorView != NULL) 241 tabView->SetTypeEditorTab(fTypeEditorView); 242 else { 243 // show the raw editor if we don't have a specialised type editor 244 tabView->Select(1); 245 } 246 247 fProbeView->AddSaveMenuItems(menu, 0); 248 fProbeView->AddPrintMenuItems(menu, menu->CountItems() - 2); 249 250 fProbeView->UpdateSizeLimits(); 251 } 252 253 254 AttributeWindow::~AttributeWindow() 255 { 256 free(fAttribute); 257 } 258 259 260 void 261 AttributeWindow::MessageReceived(BMessage *message) 262 { 263 switch (message->what) { 264 case kMsgRemoveAttribute: 265 { 266 char buffer[1024]; 267 snprintf(buffer, sizeof(buffer), 268 "Do you really want to remove the attribute \"%s\" from the file \"%s\"?\n\n" 269 "You cannot undo this action.", 270 fAttribute, Ref().name); 271 272 int32 chosen = (new BAlert("DiskProbe request", 273 buffer, "Cancel", "Remove", NULL, 274 B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go(); 275 if (chosen == 1) { 276 BNode node(&Ref()); 277 if (node.InitCheck() == B_OK) 278 node.RemoveAttr(fAttribute); 279 280 PostMessage(B_QUIT_REQUESTED); 281 } 282 break; 283 } 284 285 default: 286 ProbeWindow::MessageReceived(message); 287 break; 288 } 289 } 290 291 292 bool 293 AttributeWindow::QuitRequested() 294 { 295 if (fTypeEditorView != NULL) 296 fTypeEditorView->CommitChanges(); 297 298 bool quit = fProbeView->QuitRequested(); 299 if (!quit) 300 return false; 301 302 return ProbeWindow::QuitRequested(); 303 } 304 305 306 bool 307 AttributeWindow::Contains(const entry_ref &ref, const char *attribute) 308 { 309 return ref == Ref() && attribute != NULL && !strcmp(attribute, fAttribute); 310 } 311 312