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