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