diff --git a/src/prefs/backgrounds/BGMain.cpp b/src/prefs/backgrounds/BGMain.cpp new file mode 100644 index 0000000000..f36b612639 --- /dev/null +++ b/src/prefs/backgrounds/BGMain.cpp @@ -0,0 +1,40 @@ +/* + +"Backgrounds" by Jerome Duval (jerome.duval@free.fr) + +(C)2002 OpenBeOS under MIT license + +*/ + +#include "BGMain.h" +#include + +BGApplication::BGApplication() + :BApplication(APP_SIGNATURE) +{ + fBGWin=new BGWindow(BRect(100,100,570,325)); + fBGWin->Show(); +} + + +int main(int, char**) +{ + BGApplication myApplication; + + // This function doesn't return until the application quits + myApplication.Run(); + + return(0); +} + + +void process_refs(entry_ref dir_ref, BMessage *msg, void* reserved) +{ + BGWindow *fBGWin=new BGWindow(BRect(100,100,570,325), false); + fBGWin->ProcessRefs(dir_ref, msg); + snooze(500); + fBGWin->Show(); + + status_t exit_value; + wait_for_thread(fBGWin->Thread(), &exit_value); +} diff --git a/src/prefs/backgrounds/BGMain.h b/src/prefs/backgrounds/BGMain.h new file mode 100644 index 0000000000..b04ffc0a34 --- /dev/null +++ b/src/prefs/backgrounds/BGMain.h @@ -0,0 +1,23 @@ +/* + +"Backgrounds" by Jerome Duval (jerome.duval@free.fr) + +(C)2002 OpenBeOS under MIT license + +*/ + +#ifndef BG_WORLD_H +#define BG_WORLD_H + +#include +#include "BGWindow.h" + +#define APP_SIGNATURE "application/x-vnd.obos-Backgrounds" + +class BGApplication : public BApplication { + public: + BGApplication(); + BGWindow *fBGWin; +}; + +#endif diff --git a/src/prefs/backgrounds/BGView.cpp b/src/prefs/backgrounds/BGView.cpp new file mode 100644 index 0000000000..139c8fde38 --- /dev/null +++ b/src/prefs/backgrounds/BGView.cpp @@ -0,0 +1,1325 @@ +/* + +"Backgrounds" by Jerome Duval (jerome.duval@free.fr) + +(C)2002 OpenBeOS under MIT license + +*/ + +/* + BGView.cpp +*/ + +#include "BGView.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define APPLY_SETTINGS 'aply' +#define REVERT_SETTINGS 'rvrt' +#define DEFAULT_SETTINGS 'dflt' +#define TRY_SETTINGS 'trys' + +#define ATTRIBUTE_CHOSEN 'atch' +#define UPDATE_COLOR 'upcl' +#define ALL_WORKSPACES 'alwk' +#define CURRENT_WORKSPACE 'crwk' +#define DEFAULT_FOLDER 'dffl' +#define OTHER_FOLDER 'otfl' +#define NONE_IMAGE 'noim' +#define OTHER_IMAGE 'otim' +#define IMAGE_SELECTED 'imsl' +#define FOLDER_SELECTED 'flsl' + +#define CENTER_PLACEMENT 'cnpl' +#define MANUAL_PLACEMENT 'mnpl' +#define SCALE_PLACEMENT 'scpl' +#define TILE_PLACEMENT 'tlpl' +#define ICONLABEL_CHECKBOX 'ilcb' + +#define XY_PLACEMENT 'xypl' +#define PREVIEW_PLACEMENT 'pvpl' + +void SetRGBColor(rgb_color *col,uint8 r, uint8 g, uint8 b, uint8 a=255); + +BGView::BGView(BRect frame, const char *name, int32 resize, int32 flags) + :BView(frame,name,resize,flags), + fCurrent(NULL), + fCurrentInfo(NULL), + fPathList(1, true), + fImageList(1, true) +{ + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + /* the preview box */ + + BFont font(be_plain_font); + fPreview = new PreviewBox(BRect(10,16,160,180), "preview"); + fPreview->SetFont(&font); + fPreview->SetLabel("Preview"); + AddChild(fPreview); + + BRect xyrect(15, 135, 70, 155); + fXPlacementText = new BTextControl(xyrect, "xPlacementText", "X:", NULL, + new BMessage(XY_PLACEMENT)); + fXPlacementText->SetDivider(12.0); + fXPlacementText->TextView()->SetMaxBytes(4); + fPreview->AddChild(fXPlacementText); + + xyrect.OffsetBy(65, 0); + fYPlacementText = new BTextControl(xyrect, "yPlacementText", "Y:", NULL, + new BMessage(XY_PLACEMENT)); + fYPlacementText->SetDivider(12.0); + fYPlacementText->TextView()->SetMaxBytes(4); + fPreview->AddChild(fYPlacementText); + + for(int i=0; i<256; i++) + if(i<'0'||i>'9') { + fXPlacementText->TextView()->DisallowChar(i); + fYPlacementText->TextView()->DisallowChar(i); + } + + fPreView = new PreView(BRect(15,25,135,115), "preView", + B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_SUBPIXEL_PRECISE); + fPreview->AddChild(fPreView); + + /* the right box */ + + BBox *rightbox = new BBox(BRect(fPreview->Frame().right+10, + fPreview->Frame().top-6,this->Frame().right-10,fPreview->Frame().bottom), + "rightbox"); + AddChild(rightbox); + + fPicker=new BColorControl(BPoint(10, 110),B_CELLS_32x8,5.0,"Picker", + new BMessage(UPDATE_COLOR)); + rightbox->AddChild(fPicker); + + BRect cvrect(80, 76, 280, 96); + + fIconLabelBackground = new BCheckBox(cvrect, "iconLabelBackground", + "Icon label background", new BMessage(ICONLABEL_CHECKBOX)); + rightbox->AddChild(fIconLabelBackground); + + BMenuItem *menuItem; + fWorkspaceMenu = new BPopUpMenu("pick one"); + fWorkspaceMenu->AddItem(menuItem = new BMenuItem("All Workspaces", + new BMessage(ALL_WORKSPACES))); + fWorkspaceMenu->AddItem(menuItem = new BMenuItem("Current Workspace", + new BMessage(CURRENT_WORKSPACE))); + menuItem->SetMarked(true); + fLastWorkspaceIndex = fWorkspaceMenu->IndexOf(fWorkspaceMenu->FindMarked()); + fWorkspaceMenu->AddSeparatorItem(); + fWorkspaceMenu->AddItem(menuItem = new BMenuItem("Default folder", + new BMessage(DEFAULT_FOLDER))); + fWorkspaceMenu->AddItem(menuItem = new BMenuItem("Other folder...", + new BMessage(OTHER_FOLDER))); + fWorkspaceMenu->AddSeparatorItem(); + + fImageMenu = new BPopUpMenu("pick one"); + fImageMenu->AddItem(new BGImageMenuItem("None", -1, new BMessage(NONE_IMAGE))); + fImageMenu->AddSeparatorItem(); + fImageMenu->AddSeparatorItem(); + fImageMenu->AddItem(new BMenuItem("Other...", new BMessage(OTHER_IMAGE))); + + fPlacementMenu = new BPopUpMenu("pick one"); + fPlacementMenu->AddItem(new BMenuItem("Manual", + new BMessage(MANUAL_PLACEMENT))); + fPlacementMenu->AddItem(new BMenuItem("Center", + new BMessage(CENTER_PLACEMENT))); + fPlacementMenu->AddItem(new BMenuItem("Scale to fit", + new BMessage(SCALE_PLACEMENT))); + fPlacementMenu->AddItem(new BMenuItem("Tile", + new BMessage(TILE_PLACEMENT))); + + cvrect.OffsetBy(-70, -25); + BMenuField *placementMenuField = new BMenuField(cvrect, "placementMenuField", + "Placement:", fPlacementMenu); + placementMenuField->SetDivider(70.0); + placementMenuField->SetAlignment(B_ALIGN_RIGHT); + rightbox->AddChild(placementMenuField); + + cvrect.OffsetBy(0, -25); + BMenuField *imageMenuField = new BMenuField(cvrect, "imageMenuField", + "Image:", fImageMenu); + imageMenuField->SetDivider(70.0); + imageMenuField->SetAlignment(B_ALIGN_RIGHT); + rightbox->AddChild(imageMenuField); + + cvrect.right -= 70; + cvrect.bottom -= 2; + BMenuField *workspaceMenuField = new BMenuField(cvrect, "workspaceMenuField", + NULL, fWorkspaceMenu, true); + rightbox->SetLabel(workspaceMenuField); + + fRevert=new BButton(BRect(fPreview->Frame().left, fPreview->Frame().bottom+10, + fPreview->Frame().left+80, this->Frame().bottom-10),"RevertButton", + "Revert", new BMessage(REVERT_SETTINGS),B_FOLLOW_LEFT |B_FOLLOW_TOP, + B_WILL_DRAW | B_NAVIGABLE); + AddChild(fRevert); + + fApply=new BButton(BRect(rightbox->Frame().right-70, fPreview->Frame().bottom + +10,rightbox->Frame().right,110),"ApplyButton","Apply", + new BMessage(APPLY_SETTINGS),B_FOLLOW_LEFT |B_FOLLOW_TOP, + B_WILL_DRAW | B_NAVIGABLE); + AddChild(fApply); + +} + + +BGView::~BGView(void) +{ + delete fPanel; + delete fFolderPanel; +} + + +void +BGView::AllAttached(void) +{ + fPlacementMenu->SetTargetForItems(this); + fImageMenu->SetTargetForItems(this); + fWorkspaceMenu->SetTargetForItems(this); + fXPlacementText->SetTarget(this); + fYPlacementText->SetTarget(this); + fIconLabelBackground->SetTarget(this); + fPicker->SetTarget(this); + fApply->SetTarget(this); + fRevert->SetTarget(this); + + fPanel = new ImageFilePanel(B_OPEN_PANEL, new BMessenger(this), NULL, + B_FILE_NODE, false, NULL, new CustomRefFilter(true)); + fPanel->SetButtonLabel(B_DEFAULT_BUTTON, "Select"); + + fFolderPanel = new BFilePanel(B_OPEN_PANEL, new BMessenger(this), NULL, + B_DIRECTORY_NODE, false, NULL, new CustomRefFilter(false)); + fFolderPanel->SetButtonLabel(B_DEFAULT_BUTTON, "Select"); + + LoadSettings(); + LoadDesktopFolder(); +} + + +void +BGView::MessageReceived(BMessage *msg) +{ + //printf("what : %li\n", msg->what); + switch(msg->what) + { + case B_SIMPLE_DATA: + case B_REFS_RECEIVED: + { + //printf("refs received\n"); + RefsReceived(msg); + break; + } + case PREVIEW_PLACEMENT: + { + BString xstring, ystring; + xstring << (int)fPreView->fPoint.x; + ystring << (int)fPreView->fPoint.y; + fXPlacementText->SetText(xstring.String()); + fYPlacementText->SetText(ystring.String()); + UpdatePreview(); + UpdateButtons(); + break; + } + case MANUAL_PLACEMENT: + { + fXPlacementText->SetText("0"); + fYPlacementText->SetText("0"); + UpdatePreview(); + UpdateButtons(); + break; + } + case TILE_PLACEMENT: + case SCALE_PLACEMENT: + case CENTER_PLACEMENT: + { + fXPlacementText->SetText(""); + fYPlacementText->SetText(""); + UpdatePreview(); + UpdateButtons(); + break; + } + case ICONLABEL_CHECKBOX: + { + UpdateButtons(); + break; + } + case UPDATE_COLOR: + case XY_PLACEMENT: + { + UpdatePreview(); + UpdateButtons(); + break; + } + case CURRENT_WORKSPACE: + case ALL_WORKSPACES: + { + fImageMenu->FindItem(NONE_IMAGE)->SetLabel("None"); + fLastWorkspaceIndex = fWorkspaceMenu->IndexOf( + fWorkspaceMenu->FindMarked()); + if(!fCurrent->IsDesktop()) { + fPreview->SetDesktop(true); + LoadDesktopFolder(); + } else + UpdateButtons(); + break; + } + case DEFAULT_FOLDER: + { + fImageMenu->FindItem(NONE_IMAGE)->SetLabel("None"); + fLastWorkspaceIndex = fWorkspaceMenu->IndexOf( + fWorkspaceMenu->FindMarked()); + fPreview->SetDesktop(false); + LoadDefaultFolder(); + break; + } + case OTHER_FOLDER: + { + fFolderPanel->Show(); + break; + } + case OTHER_IMAGE: + { + fPanel->Show(); + break; + } + case B_CANCEL: + { + printf("cancel received\n"); + void* pointer; + msg->FindPointer("source", &pointer); + if(pointer == fPanel) { + if(fLastImageIndex>=0) + FindImageItem(fLastImageIndex)->SetMarked(true); + else + fImageMenu->ItemAt(0)->SetMarked(true); + } + else if(pointer == fFolderPanel) { + if(fLastWorkspaceIndex>=0) + fWorkspaceMenu->ItemAt(fLastWorkspaceIndex)->SetMarked(true); + } + break; + } + case IMAGE_SELECTED: + case NONE_IMAGE: + { + fLastImageIndex = ((BGImageMenuItem*)fImageMenu->FindMarked()) + ->ImageIndex(); + UpdatePreview(); + UpdateButtons(); + break; + } + case FOLDER_SELECTED: + { + fImageMenu->FindItem(NONE_IMAGE)->SetLabel("Default"); + fLastWorkspaceIndex = fWorkspaceMenu->IndexOf( + fWorkspaceMenu->FindMarked()); + fPreview->SetDesktop(false); + LoadRecentFolder(*fPathList.ItemAt(fWorkspaceMenu->IndexOf( + fWorkspaceMenu->FindMarked()) - 6)); + break; + } + case APPLY_SETTINGS: + { + Save(); + //NotifyServer(); + thread_id notify_thread; + notify_thread = spawn_thread(BGView::NotifyThread, "notifyServer", + B_NORMAL_PRIORITY, this); + resume_thread(notify_thread); + UpdateButtons(); + break; + } + case REVERT_SETTINGS: + { + UpdateWithCurrent(); + break; + } + default: + BView::MessageReceived(msg); + break; + } +} + + +void +BGView::LoadDesktopFolder(void) +{ + BPath path; + if(find_directory(B_DESKTOP_DIRECTORY, &path) == B_OK) { + status_t err; + err = get_ref_for_path(path.Path(), &fCurrent_ref); + if(err!=B_OK) + printf("error in LoadDesktopSettings\n"); + LoadFolder(true); + } +} + + +void +BGView::LoadDefaultFolder(void) +{ + BPath path; + if(find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) { + BString pathString = path.Path(); + pathString << "/Tracker/DefaultFolderTemplate"; + status_t err; + err = get_ref_for_path(pathString.String(), &fCurrent_ref); + if(err!=B_OK) + printf("error in LoadDefaultFolderSettings\n"); + LoadFolder(false); + } +} + + +void +BGView::LoadRecentFolder(BPath path) +{ + status_t err; + err = get_ref_for_path(path.Path(), &fCurrent_ref); + if(err!=B_OK) + printf("error in LoadRecentFolder\n"); + LoadFolder(false); +} + + +void +BGView::LoadFolder(bool isDesktop) +{ + if(fCurrent) { + delete fCurrent; + fCurrent = NULL; + } + BNode node(&fCurrent_ref); + if(node.InitCheck() == B_OK) { + fCurrent = BackgroundImage::GetBackgroundImage(&node, isDesktop, this); + } else { + printf("pb with the folder node\n"); + } + UpdateWithCurrent(); +} + + +void +BGView::UpdateWithCurrent(void) +{ + if(!fCurrent) + printf("current null\n"); + if(fCurrent) { + fPlacementMenu->FindItem(SCALE_PLACEMENT)->SetEnabled(fCurrent->IsDesktop()); + fPlacementMenu->FindItem(CENTER_PLACEMENT)->SetEnabled(fCurrent->IsDesktop()); + + if(fWorkspaceMenu->IndexOf(fWorkspaceMenu->FindMarked())>5) + fImageMenu->FindItem(NONE_IMAGE)->SetLabel("Default"); + else + fImageMenu->FindItem(NONE_IMAGE)->SetLabel("None"); + + for(int32 i=fImageMenu->CountItems()-5; i>=0; i--) + fImageMenu->RemoveItem(2); + + for(int32 i=fImageList.CountItems()-1; i>=0; i--) { + BMessage *message = new BMessage(IMAGE_SELECTED); + AddItem(new BGImageMenuItem(GetImage(i)->GetName(), i, message)); + } + + fImageMenu->SetTargetForItems(this); + + fCurrentInfo = fCurrent->ImageInfoForWorkspace(current_workspace()); + + if(!fCurrentInfo) { + + fImageMenu->FindItem(NONE_IMAGE)->SetMarked(true); + fPlacementMenu->FindItem(MANUAL_PLACEMENT)->SetMarked(true); + + } else { + if(fCurrentInfo->fEraseTextWidgetBackground) + fIconLabelBackground->SetValue(B_CONTROL_ON); + else + fIconLabelBackground->SetValue(B_CONTROL_OFF); + + BString xtext, ytext; + int32 cmd = 0; + switch(fCurrentInfo->fMode) + { + case BackgroundImage::kCentered: + cmd = CENTER_PLACEMENT; + break; + case BackgroundImage::kScaledToFit: + cmd = SCALE_PLACEMENT; + break; + case BackgroundImage::kAtOffset: + cmd = MANUAL_PLACEMENT; + xtext << (int)fCurrentInfo->fOffset.x; + ytext << (int)fCurrentInfo->fOffset.y; + break; + case BackgroundImage::kTiled: + cmd = TILE_PLACEMENT; + break; + } + if(cmd!=0) + fPlacementMenu->FindItem(cmd)->SetMarked(true); + fXPlacementText->SetText(xtext.String()); + fYPlacementText->SetText(ytext.String()); + + fLastImageIndex = fCurrentInfo->fImageIndex; + FindImageItem(fLastImageIndex)->SetMarked(true); + } + + rgb_color color; + if(fCurrent->IsDesktop()) { + color = BScreen().DesktopColor(); + fPicker->SetEnabled(true); + } else { + SetRGBColor(&color,255,255,255); + fPicker->SetEnabled(false); + } + fPicker->SetValue(color); + + UpdatePreview(); + UpdateButtons(); + } +} + + +void +BGView::Save() +{ + bool eraseTextWidgetBackground = + (fIconLabelBackground->Value()==B_CONTROL_ON); + BackgroundImage::Mode mode = FindPlacementMode(); + BPoint offset(atoi(fXPlacementText->Text()), atoi(fYPlacementText->Text())); + + if(!fCurrent->IsDesktop()) { + if(fCurrentInfo==NULL) { + fCurrentInfo = new BackgroundImage::BackgroundImageInfo(B_ALL_WORKSPACES, + fLastImageIndex, mode, offset, eraseTextWidgetBackground, 0, 0); + fCurrent->Add(fCurrentInfo); + } else { + fCurrentInfo->fEraseTextWidgetBackground = eraseTextWidgetBackground; + fCurrentInfo->fMode = mode; + if(fCurrentInfo->fMode == BackgroundImage::kAtOffset) + fCurrentInfo->fOffset = offset; + fCurrentInfo->fImageIndex = fLastImageIndex; + } + } else { + uint32 workspaceMask = 1; + uint32 workspace = current_workspace(); + for ( ; workspace; workspace--) + workspaceMask *= 2; + + if(fCurrentInfo!=NULL) { + if(fWorkspaceMenu->FindItem(CURRENT_WORKSPACE)->IsMarked()) { + + if(fCurrentInfo->fWorkspace != workspaceMask) { + fCurrentInfo->fWorkspace = fCurrentInfo->fWorkspace + ^ workspaceMask; + fCurrentInfo = new BackgroundImage::BackgroundImageInfo( + workspaceMask, fLastImageIndex, mode, offset, + eraseTextWidgetBackground, fCurrentInfo->fImageSet, + fCurrentInfo->fCacheMode); + fCurrent->Add(fCurrentInfo); + } else { + fCurrentInfo->fEraseTextWidgetBackground = + eraseTextWidgetBackground; + fCurrentInfo->fMode = mode; + if(fCurrentInfo->fMode == BackgroundImage::kAtOffset) { + fCurrentInfo->fOffset = offset; + } + fCurrentInfo->fImageIndex = fLastImageIndex; + } + + } else { + fCurrent->RemoveAll(); + fCurrentInfo = new BackgroundImage::BackgroundImageInfo( + B_ALL_WORKSPACES, fLastImageIndex, mode, offset, + eraseTextWidgetBackground, fCurrent->GetShowingImageSet(), + fCurrentInfo->fCacheMode); + fCurrent->Add(fCurrentInfo); + } + } else { + if(fWorkspaceMenu->FindItem(CURRENT_WORKSPACE)->IsMarked()) { + fCurrentInfo = new BackgroundImage::BackgroundImageInfo( + workspaceMask, fLastImageIndex, mode, offset, + eraseTextWidgetBackground, fCurrent->GetShowingImageSet(), 0); + } else { + fCurrent->RemoveAll(); + fCurrentInfo = new BackgroundImage::BackgroundImageInfo( + B_ALL_WORKSPACES, fLastImageIndex, mode, offset, + eraseTextWidgetBackground, fCurrent->GetShowingImageSet(), 0); + } + fCurrent->Add(fCurrentInfo); + } + + if(fCurrentInfo->fWorkspace == B_ALL_WORKSPACES) + for(int32 i=0; iValueAsColor(), i, true); + else + BScreen().SetDesktopColor(fPicker->ValueAsColor(), true); + } + BNode node(&fCurrent_ref); + fCurrent->SetBackgroundImage(&node); +} + + +void +BGView::NotifyServer() +{ + BMessenger tracker( "application/x-vnd.Be-TRAK" ); + if(fCurrent->IsDesktop()) { + tracker.SendMessage( new BMessage(B_RESTORE_BACKGROUND_IMAGE)); + } else { + int32 i = -1; + BMessage reply; + int32 err; + BEntry currentEnt( &fCurrent_ref ); + BPath currentPath( ¤tEnt ); + bool isCustomFolder = !fWorkspaceMenu->FindItem(DEFAULT_FOLDER)->IsMarked(); + + do { + i++; + + /* scripting message */ + BMessage msg( B_GET_PROPERTY ); + + /* look at the "Poses" in every Tracker window */ + msg.AddSpecifier( "Poses" ); + msg.AddSpecifier( "Window", i ); + + reply.MakeEmpty(); + + tracker.SendMessage( &msg, &reply ); + + /* break out of the loop when we're at the end of + * the windows + */ + if( reply.what == B_MESSAGE_NOT_UNDERSTOOD && + reply.FindInt32( "error", &err ) == B_OK && + err == B_BAD_INDEX ) + break; + + /* don't stop for windows that don't understand + * a request for "Poses"; they're not displaying + * folders + */ + if( reply.what == B_MESSAGE_NOT_UNDERSTOOD && + reply.FindInt32( "error", &err ) == B_OK && + err != B_BAD_SCRIPT_SYNTAX ) + continue; + + BMessenger m; + if( reply.FindMessenger( "result", &m ) != B_OK) + continue; + /* m is the messenger of a Tracker window with + * a folder inside + */ + + if(isCustomFolder) { + /* found a Window with a Poses, ask for its Path */ + msg.MakeEmpty(); + msg.what = B_GET_PROPERTY; + msg.AddSpecifier( "Path" ); + msg.AddSpecifier( "Poses" ); + msg.AddSpecifier( "Window", i ); + + reply.MakeEmpty(); + + tracker.SendMessage( &msg, &reply ); + + /* go on with the next if this din't have a Path */ + if( reply.what == B_MESSAGE_NOT_UNDERSTOOD ) continue; + + /* dig out the Path */ + entry_ref ref; + if( reply.FindRef( "result", &ref ) == B_OK ) { + BEntry ent( &ref ); + BPath path( &ent ); + + /* these are not the Paths you're looking for */ + if( currentPath != path) continue; + } + } + + m.SendMessage( B_RESTORE_BACKGROUND_IMAGE ); + } while( true ); + } +} + + +int32 BGView::NotifyThread(void *data) { + BGView *bgView = (BGView*)data; + bgView->NotifyServer(); + return B_OK; +} + + +void +BGView::SaveSettings(void) +{ + BPath path; + if(find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) { + path.Append(SETTINGS_FILE); + BFile file(path.Path(),B_READ_WRITE|B_CREATE_FILE|B_ERASE_FILE); + + BPoint point = Window()->Frame().LeftTop(); + if(fSettings.ReplacePoint("pos", point)!=B_OK) + fSettings.AddPoint("pos", point); + + entry_ref ref; + BEntry entry; + BPath path; + + fPanel->GetPanelDirectory(&ref); + entry.SetTo(&ref); + entry.GetPath(&path); + if(fSettings.ReplaceString("paneldir", path.Path())!=B_OK) + fSettings.AddString("paneldir", path.Path()); + + fFolderPanel->GetPanelDirectory(&ref); + entry.SetTo(&ref); + entry.GetPath(&path); + if(fSettings.ReplaceString("folderpaneldir", path.Path())!=B_OK) + fSettings.AddString("folderpaneldir", path.Path()); + + fSettings.RemoveName("recentfolder"); + for(int i=0; iPath()); + + fSettings.Flatten(&file); + } +} + + +void +BGView::LoadSettings(void) +{ + fSettings.MakeEmpty(); + + BPath path; + if(find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) { + path.Append(SETTINGS_FILE); + BFile file(path.Path(),B_READ_ONLY); + if((file.InitCheck()==B_OK)&&(fSettings.Unflatten(&file)==B_OK)) + { + fSettings.PrintToStream(); + + BPoint point; + if(fSettings.FindPoint("pos", &point)==B_OK) + Window()->MoveTo(point); + + BString string; + if(fSettings.FindString("paneldir", &string)==B_OK) + fPanel->SetPanelDirectory(string.String()); + + if(fSettings.FindString("folderpaneldir", &string)==B_OK) + fFolderPanel->SetPanelDirectory(string.String()); + + int32 index = 0; + while(fSettings.FindString("recentfolder", index, &string)==B_OK) + { + BPath path(string.String()); + int32 i = AddPath(path); + BString s; + s << "Folder: " << path.Leaf(); + BMenuItem *item = new BMenuItem(s.String(), + new BMessage(FOLDER_SELECTED)); + fWorkspaceMenu->AddItem(item, -i-1+6); + index++; + } + fWorkspaceMenu->SetTargetForItems(this); + + printf("Settings Loaded\n"); + } else + { + printf("Error unflattening settings file %s\n",path.Path()); + } + } +} + + +void +SetRGBColor(rgb_color *col,uint8 r, uint8 g, uint8 b, uint8 a=255) +{ + col->red=r; + col->green=g; + col->blue=b; + col->alpha=a; +} + + +void +BGView::WorkspaceActivated(uint32 oldWorkspaces, bool active) +{ + if(true) { + UpdateWithCurrent(); + } +} + + +void +BGView::UpdatePreview() +{ + bool imageEnabled = !(fImageMenu->FindItem(NONE_IMAGE)->IsMarked()); + if(fPlacementMenu->IsEnabled()^imageEnabled) + fPlacementMenu->SetEnabled(imageEnabled); + if(fIconLabelBackground->IsEnabled()^imageEnabled) + fIconLabelBackground->SetEnabled(imageEnabled); + bool textEnabled = (fPlacementMenu->FindItem(MANUAL_PLACEMENT)->IsMarked()) + &&imageEnabled; + if(fXPlacementText->IsEnabled()^textEnabled) + fXPlacementText->SetEnabled(textEnabled); + if(fYPlacementText->IsEnabled()^textEnabled) + fYPlacementText->SetEnabled(textEnabled); + fXPlacementText->TextView()->MakeSelectable(textEnabled); + fYPlacementText->TextView()->MakeSelectable(textEnabled); + fXPlacementText->TextView()->MakeEditable(textEnabled); + fYPlacementText->TextView()->MakeEditable(textEnabled); + int32 index = ((BGImageMenuItem*)fImageMenu->FindMarked())->ImageIndex(); + fPreView->ClearViewBitmap(); + if(index>=0) { + BBitmap *bitmap = GetImage(index)->GetBitmap(); + if(bitmap) { + + BackgroundImage::BackgroundImageInfo *info = + new BackgroundImage::BackgroundImageInfo(0, index, + FindPlacementMode(), BPoint(atoi(fXPlacementText->Text()), + atoi(fYPlacementText->Text())), + (fIconLabelBackground->Value()==B_CONTROL_ON), 0, 0); + if(info->fMode == BackgroundImage::kAtOffset) { + fPreView->SetEnabled(true); + fPreView->fPoint.x = atoi(fXPlacementText->Text()); + fPreView->fPoint.y = atoi(fYPlacementText->Text()); + } else { + fPreView->SetEnabled(false); + } + + fPreView->fImageBounds = BRect(bitmap->Bounds()); + fCurrent->Show(info, fPreView); + } + } + fPreView->SetViewColor(fPicker->ValueAsColor()); + fPreView->Invalidate(); +} + + +BackgroundImage::Mode +BGView::FindPlacementMode() +{ + BackgroundImage::Mode mode = BackgroundImage::kAtOffset; + if(fPlacementMenu->FindItem(CENTER_PLACEMENT)->IsMarked()) + mode = BackgroundImage::kCentered; + if(fPlacementMenu->FindItem(SCALE_PLACEMENT)->IsMarked()) + mode = BackgroundImage::kScaledToFit; + if(fPlacementMenu->FindItem(MANUAL_PLACEMENT)->IsMarked()) + mode = BackgroundImage::kAtOffset; + if(fPlacementMenu->FindItem(TILE_PLACEMENT)->IsMarked()) + mode = BackgroundImage::kTiled; + return mode; +} + + +void +BGView::UpdateButtons() +{ + bool hasChanged = false; + if(fPicker->IsEnabled() && ((fPicker->ValueAsColor().green != + BScreen().DesktopColor().green) + ||(fPicker->ValueAsColor().red != BScreen().DesktopColor().red) + ||(fPicker->ValueAsColor().blue != BScreen().DesktopColor().blue))) + hasChanged = true; + else if(fCurrentInfo) { + if((fIconLabelBackground->Value()==B_CONTROL_ON) ^ + fCurrentInfo->fEraseTextWidgetBackground) + hasChanged = true; + else if(FindPlacementMode() != fCurrentInfo->fMode) + hasChanged = true; + else if(fCurrentInfo->fImageIndex != + ((BGImageMenuItem*)fImageMenu->FindMarked())->ImageIndex()) + hasChanged = true; + else if(fCurrent->IsDesktop()&&((fCurrentInfo->fWorkspace != B_ALL_WORKSPACES) + ^ (fWorkspaceMenu->FindItem(CURRENT_WORKSPACE)->IsMarked()))) + hasChanged = true; + else if(fCurrentInfo->fMode == BackgroundImage::kAtOffset) { + BString oldString, newString; + oldString << (int)fCurrentInfo->fOffset.x; + if(oldString != BString(fXPlacementText->Text())) + hasChanged = true; + oldString = ""; + oldString << (int)fCurrentInfo->fOffset.y; + if(oldString != BString(fYPlacementText->Text())) + hasChanged = true; + } + } else { + if(fImageMenu->IndexOf(fImageMenu->FindMarked())>0) + hasChanged = true; + } + + fApply->SetEnabled(hasChanged); + fRevert->SetEnabled(hasChanged); +} + + +void +BGView::RefsReceived(BMessage *msg) +{ + entry_ref ref; + int32 i = 0; + BMimeType imageType("image"); + while (msg->FindRef("refs", i++, &ref) == B_OK) { + + BPath path; + BEntry entry(&ref, true); + path.SetTo(&entry); + BNode node(&entry); + + if (node.IsFile()) { + BNodeInfo nodeInfo(&node); + char fileType[256]; + if(nodeInfo.GetType(fileType)!=B_OK) + continue; + BMimeType refType(fileType); + if(!imageType.Contains(&refType)) + continue; + BGImageMenuItem *item; + int32 index = AddImage(path); + if(index>=0) { + item = FindImageItem(index); + fLastImageIndex = index; + } else { + const char* name = GetImage(-index-1)->GetName(); + item = new BGImageMenuItem(name, -index-1, + new BMessage(IMAGE_SELECTED)); + AddItem(item); + item->SetTarget(this); + fLastImageIndex = -index-1; + } + item->SetMarked(true); + BMessenger messenger(this); + messenger.SendMessage(IMAGE_SELECTED); + } else if(node.IsDirectory()) { + BMenuItem *item; + int32 index = AddPath(path); + if(index>=0) { + item = fWorkspaceMenu->ItemAt(index+6); + fLastWorkspaceIndex = index+6; + } else { + BString s; + s << "Folder: " << path.Leaf(); + item = new BMenuItem(s.String(), new BMessage(FOLDER_SELECTED)); + fWorkspaceMenu->AddItem(item, -index-1+6); + item->SetTarget(this); + fLastWorkspaceIndex = -index-1 + 6; + } + item->SetMarked(true); + BMessenger messenger(this); + messenger.SendMessage(FOLDER_SELECTED); + } + } +} + + +int32 +BGView::AddPath(BPath path) +{ + int32 count = fPathList.CountItems(); + int32 index=0; + for(; indexPath()).ICompare(BString(path.Path()))); + if(c == 0) + return index; + else if(c > 0) + break; + } + fPathList.AddItem(new BPath(path), index); + return -index-1; +} + + +int32 +BGView::AddImage(BPath path) +{ + int32 count = fImageList.CountItems(); + int32 index=0; + for(; indexGetPath() == path) + return index; + } + fImageList.AddItem(new Image(path)); + + return -index-1; +} + + +void +BGView::ProcessRefs(entry_ref dir_ref, BMessage* msg) +{ + fWorkspaceMenu->FindItem(DEFAULT_FOLDER)->SetMarked(true); + BMessenger messenger(this); + messenger.SendMessage(DEFAULT_FOLDER); + if(msg->CountNames(B_REF_TYPE)>0) { + messenger.SendMessage(msg); + } else { + BMessage message(B_REFS_RECEIVED); + message.AddRef("refs", &dir_ref); + messenger.SendMessage(&message); + } +} + + +Image* +BGView::GetImage(int32 imageIndex) +{ + return fImageList.ItemAt(imageIndex); +} + + +BGImageMenuItem* +BGView::FindImageItem(const int32 imageIndex) +{ + if(imageIndex<0) + return (BGImageMenuItem *)fImageMenu->ItemAt(0); + int32 count = fImageMenu->CountItems() - 2; + int32 index=2; + for(; indexItemAt(index); + if(image->ImageIndex() == imageIndex) + return image; + } + return NULL; +} + + +bool +BGView::AddItem(BGImageMenuItem *item) +{ + int32 count = fImageMenu->CountItems() - 2; + int32 index=2; + for(; indexItemAt(index); + int c = (BString(image->Label()).ICompare(BString(item->Label()))); + if(c > 0) + break; + } + return fImageMenu->AddItem(item, index); +} + + +PreView::PreView(BRect frame, const char *name, int32 resize, int32 flags) + :BControl(frame,name,NULL, NULL, resize,flags) +{ + +} + + +void +PreView::AttachedToWindow() { + rgb_color color = ViewColor(); + BControl::AttachedToWindow(); + SetViewColor(color); +} + + +void +PreView::MouseDown(BPoint point) +{ + if (IsEnabled() && Bounds().Contains(point)) { + uint32 buttons; + GetMouse(&point, &buttons); + if(buttons & B_PRIMARY_MOUSE_BUTTON) { + fOldPoint = point; + SetTracking(true); + BScreen().GetMode(&mode); + x_ratio = Bounds().Width() / mode.virtual_width; + y_ratio = Bounds().Height() / mode.virtual_height; + SetMouseEventMask(B_POINTER_EVENTS, + B_LOCK_WINDOW_FOCUS | B_NO_POINTER_HISTORY); + } + } +} + + +void +PreView::MouseUp(BPoint point) +{ + if(IsTracking()) + SetTracking(false); +} + + +void +PreView::MouseMoved(BPoint point, uint32 transit, const BMessage *message) +{ + if(IsEnabled()) + SetViewCursor(B_CURSOR_SYSTEM_DEFAULT); + if(IsTracking()) + { + float x, y; + x = fPoint.x + (point.x - fOldPoint.x)/ x_ratio; + y = fPoint.y + (point.y - fOldPoint.y)/ y_ratio; + bool min, max, mustSend = false; + min = (x > -fImageBounds.Width()); + max = (x < mode.virtual_width); + if( min && max) { + fOldPoint.x = point.x; + fPoint.x = x; + mustSend = true; + } else { + if(!min && fPoint.x > -fImageBounds.Width()) { + fPoint.x = -fImageBounds.Width(); + fOldPoint.x = point.x - (x - fPoint.x) * x_ratio; + mustSend = true; + } + if(!max && fPoint.x < mode.virtual_width) { + fPoint.x = mode.virtual_width; + fOldPoint.x = point.x - (x - fPoint.x) * x_ratio; + mustSend = true; + } + } + + min = (y > -fImageBounds.Height()); + max = (y < mode.virtual_height); + if(min && max) { + fOldPoint.y = point.y; + fPoint.y = y; + mustSend = true; + } else { + if(!min && fPoint.y > -fImageBounds.Height()) { + fPoint.y = -fImageBounds.Height(); + fOldPoint.y = point.y - (y - fPoint.y) * y_ratio; + mustSend = true; + } + if(!max && fPoint.y < mode.virtual_height) { + fPoint.y = mode.virtual_height; + fOldPoint.y = point.y - (y - fPoint.y) * y_ratio; + mustSend = true; + } + } + + if(mustSend) { + BMessenger messenger(Parent()); + messenger.SendMessage(PREVIEW_PLACEMENT); + } + } + BControl::MouseMoved(point, transit, message); +} + + +PreviewBox::PreviewBox(BRect frame, const char *name) + :BBox(frame,name) +{ + fIsDesktop = true; +} + + +void +PreviewBox::Draw(BRect rect) +{ + rgb_color color = HighColor(); + BPoint points[] = { BPoint(11,19), BPoint(139,19), BPoint(141,21), + BPoint(141,119), BPoint(139,121), BPoint(118,121), + BPoint(118,126), BPoint(117,127), BPoint(33,127), + BPoint(32,126), BPoint(32,121),BPoint(11,121), + BPoint(9,119),BPoint(9,21),BPoint(11,19) }; + + SetHighColor(LowColor()); + FillRect(BRect(9,19,141,127)); + if(fIsDesktop) { + SetHighColor(184,184,184); + FillPolygon(points, 15); + SetHighColor(96,96,96); + StrokePolygon(points, 15); + FillRect(BRect(107,121,111,123)); + SetHighColor(0,0,0); + StrokeRect(BRect(14,24,136,116)); + SetHighColor(0,255,0); + FillRect(BRect(101,122,103,123)); + } else { + SetHighColor(152,152,152); + StrokeLine(BPoint(11,13), BPoint(67,13)); + StrokeLine(BPoint(67,21)); + StrokeLine(BPoint(139,21)); + StrokeLine(BPoint(139,119)); + StrokeLine(BPoint(11,119)); + StrokeLine(BPoint(11,13)); + StrokeRect(BRect(14,24,136,116)); + SetHighColor(255,203,0); + FillRect(BRect(12,14,66,21)); + SetHighColor(240,240,240); + StrokeRect(BRect(12,22,137,117)); + StrokeLine(BPoint(138,22), BPoint(138,22)); + StrokeLine(BPoint(12,118), BPoint(12,118)); + SetHighColor(200,200,200); + StrokeRect(BRect(13,23,138,118)); + } + SetHighColor(color); + BBox::Draw(rect); +} + + +void +PreviewBox::SetDesktop(bool isDesktop) +{ + fIsDesktop = isDesktop; + Invalidate(); +} + + +ImageFilePanel::ImageFilePanel(file_panel_mode mode, BMessenger *target, + const entry_ref *start_directory, uint32 node_flavors, + bool allow_multiple_selection, BMessage *message, BRefFilter *filter, + bool modal, bool hide_when_done) + :BFilePanel(mode,target,start_directory, node_flavors, + allow_multiple_selection,message,filter,modal,hide_when_done), + imageView(NULL) +{ +} + + +void +ImageFilePanel::Show() +{ + if(imageView==NULL) { + Window()->Lock(); + BView *background = Window()->ChildAt(0); + uint32 poseViewResizingMode = + background->FindView("PoseView")->ResizingMode(); + uint32 countVwResizingMode = + background->FindView("CountVw")->ResizingMode(); + uint32 vScrollBarResizingMode = + background->FindView("VScrollBar")->ResizingMode(); + uint32 hScrollBarResizingMode = + background->FindView("HScrollBar")->ResizingMode(); + + background->FindView("PoseView")->SetResizingMode(B_FOLLOW_LEFT|B_FOLLOW_TOP); + background->FindView("CountVw")->SetResizingMode(B_FOLLOW_LEFT|B_FOLLOW_TOP); + background->FindView("VScrollBar")->SetResizingMode(B_FOLLOW_LEFT|B_FOLLOW_TOP); + background->FindView("HScrollBar")->SetResizingMode(B_FOLLOW_LEFT|B_FOLLOW_TOP); + Window()->ResizeBy(0, 70); + background->FindView("PoseView")->SetResizingMode(poseViewResizingMode); + background->FindView("CountVw")->SetResizingMode(countVwResizingMode); + background->FindView("VScrollBar")->SetResizingMode(vScrollBarResizingMode); + background->FindView("HScrollBar")->SetResizingMode(hScrollBarResizingMode); + + BRect rect(background->Bounds().left+15,background->Bounds().bottom-94, + background->Bounds().left+122,background->Bounds().bottom-15); + imageView = new BView(rect, "ImageView", B_FOLLOW_LEFT|B_FOLLOW_BOTTOM, + B_SUBPIXEL_PRECISE); + imageView->SetViewColor(background->ViewColor()); + background->AddChild(imageView); + + rect = BRect(background->Bounds().left+132,background->Bounds().bottom-85, + background->Bounds().left+250,background->Bounds().bottom-65); + resolutionView = new BStringView(rect, "ResolutionView", NULL, + B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); + background->AddChild(resolutionView); + + rect.OffsetBy(0, -16); + imageTypeView = new BStringView(rect, "ImageTypeView", NULL, + B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); + background->AddChild(imageTypeView); + Window()->Unlock(); + } + BFilePanel::Show(); +} + + +void +ImageFilePanel::SelectionChanged(void) +{ + entry_ref ref; + Rewind(); + if(GetNextSelectedRef(&ref)==B_OK) { + BEntry entry(&ref); + BNode node(&ref); + imageView->ClearViewBitmap(); + + if(node.IsFile()) { + BBitmap *bitmap = BTranslationUtils::GetBitmap(&ref); + + if(bitmap!=NULL) { + BRect dest(imageView->Bounds()); + if(bitmap->Bounds().Width()>bitmap->Bounds().Height()) { + dest.InsetBy(0, (dest.Height()+1 - + ((bitmap->Bounds().Height()+1) / + (bitmap->Bounds().Width()+1) * (dest.Width()+1)))/2); + } else { + dest.InsetBy((dest.Width()+1 - + ((bitmap->Bounds().Width()+1) / + (bitmap->Bounds().Height()+1) * (dest.Height()+1)))/2, 0); + } + imageView->SetViewBitmap(bitmap, bitmap->Bounds(), dest, + B_FOLLOW_LEFT | B_FOLLOW_TOP, 0); + + BString resolution; + resolution << "Resolution: " << (int)(bitmap->Bounds().Width()+1) + << "x" << (int)(bitmap->Bounds().Height()+1); + resolutionView->SetText(resolution.String()); + delete bitmap; + + BNode node(&ref); + BNodeInfo nodeInfo(&node); + char fileType[256]; + if(nodeInfo.GetType(fileType)==B_OK) + { + if(strncmp(fileType, "image/jpeg", 10)==0) + imageTypeView->SetText("JPEG Image"); + else + imageTypeView->SetText(""); + } + } + } else { + resolutionView->SetText(""); + imageTypeView->SetText(""); + } + imageView->Invalidate(); + resolutionView->Invalidate(); + } + BFilePanel::SelectionChanged(); +} + + +CustomRefFilter::CustomRefFilter(bool imageFiltering) + : BRefFilter(), + fImageFiltering(imageFiltering) +{ +} + + +bool +CustomRefFilter::Filter(const entry_ref *ref, BNode* node, struct stat *st, + const char *filetype) +{ + if(fImageFiltering){ + if(node->IsDirectory()) + return true; + else { + BMimeType imageType("image"), refType(filetype); + if(imageType.Contains(&refType)) + return true; + } + return false; + } else { + return (node->IsDirectory()); + } +} + + +BGImageMenuItem::BGImageMenuItem(const char *label, int32 imageIndex, + BMessage *message, char shortcut, uint32 modifiers) + :BMenuItem(label, message, shortcut, modifiers), + fImageIndex(imageIndex) +{ +} diff --git a/src/prefs/backgrounds/BGView.h b/src/prefs/backgrounds/BGView.h new file mode 100644 index 0000000000..15f55f7312 --- /dev/null +++ b/src/prefs/backgrounds/BGView.h @@ -0,0 +1,153 @@ +/* + +"Backgrounds" by Jerome Duval (jerome.duval@free.fr) + +(C)2002 OpenBeOS under MIT license + +*/ + +#ifndef BG_VIEW_H_ +#define BG_VIEW_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "BackgroundImage.h" + +#define SETTINGS_FILE "Backgrounds_settings" + +class BGImageMenuItem : public BMenuItem { + public: + BGImageMenuItem(const char *label, int32 imageIndex, BMessage *message, + char shortcut=0, uint32 modifiers=0); + int32 ImageIndex() { return fImageIndex; } + private: + int32 fImageIndex; +}; + + +class CustomRefFilter : public BRefFilter { + public: + CustomRefFilter(bool imageFiltering); + bool Filter(const entry_ref *ref, BNode* node, struct stat *st, + const char *filetype); + protected: + bool fImageFiltering; // true for images only, false for directory only +}; + + +class ImageFilePanel : public BFilePanel { + public: + ImageFilePanel(file_panel_mode mode = B_OPEN_PANEL, + BMessenger *target = 0, const entry_ref *start_directory = 0, + uint32 node_flavors = 0, bool allow_multiple_selection = true, + BMessage *message = 0, BRefFilter * = 0, + bool modal = false, bool hide_when_done = true); + virtual void SelectionChanged(void); + void Show(void); + + protected: + BView *imageView; + BStringView *resolutionView, *imageTypeView; +}; + + +class PreviewBox : public BBox { + public: + PreviewBox(BRect frame, const char *name); + void Draw(BRect rect); + void SetDesktop(bool isDesktop); + protected: + bool fIsDesktop; +}; + + +class PreView : public BControl { + public: + PreView(BRect frame, const char *name, int32 resize, int32 flags); + BPoint fPoint; + BRect fImageBounds; + protected: + void MouseDown(BPoint point); + void MouseUp(BPoint point); + void MouseMoved(BPoint point, uint32 transit, const BMessage *message); + void AttachedToWindow(); + + BPoint fOldPoint; + float x_ratio,y_ratio; + display_mode mode; +}; + + +class BGView : public BView { + public: + BGView(BRect frame, const char *name, int32 resize, int32 flags); + ~BGView(void); + + void SaveSettings(void); + void WorkspaceActivated(uint32 oldWorkspaces, bool active); + int32 AddImage(BPath path); + Image* GetImage(int32 imageIndex); + void ProcessRefs(entry_ref dir_ref, BMessage* msg); + + protected: + void Save(void); + void NotifyServer(void); + void LoadSettings(void); + void AllAttached(void); + void MessageReceived(BMessage *msg); + void LoadDesktopFolder(void); + void LoadDefaultFolder(void); + void LoadFolder(bool isDesktop); + void LoadRecentFolder(BPath path); + void UpdateWithCurrent(void); + void UpdatePreview(void); + void UpdateButtons(void); + void RefsReceived(BMessage *msg); + int32 AddPath(BPath path); + + static int32 NotifyThread(void *data); + + BGImageMenuItem *FindImageItem(const int32 imageIndex); + bool AddItem(BGImageMenuItem *item); + + BackgroundImage::Mode FindPlacementMode(); + + BColorControl *fPicker; // color picker + BButton *fApply,*fRevert; // apply and revert buttons + BCheckBox *fIconLabelBackground; // label ckeckbox + BMenu* fPlacementMenu, *fImageMenu, *fWorkspaceMenu; // the three comboboxes + BTextControl *fXPlacementText, *fYPlacementText; // x and y textboxes + PreView *fPreView; // the view for previewing the result + PreviewBox *fPreview; // the box which draws a computer/folder + BFilePanel *fFolderPanel; // the file panels for folders + ImageFilePanel *fPanel; // the file panels for images + + BackgroundImage *fCurrent; // the current BackgroundImage object + BackgroundImage::BackgroundImageInfo *fCurrentInfo;//the current BackgroundImageInfo object + entry_ref fCurrent_ref; // the entry for the node which holds current + int32 fLastImageIndex, fLastWorkspaceIndex; // last indexes for cancel + BMessage fSettings; // settings loaded from settings directory + + BObjectList fPathList; + BObjectList fImageList; +}; + +#endif diff --git a/src/prefs/backgrounds/BGWindow.cpp b/src/prefs/backgrounds/BGWindow.cpp new file mode 100644 index 0000000000..a96bd0524f --- /dev/null +++ b/src/prefs/backgrounds/BGWindow.cpp @@ -0,0 +1,42 @@ +/* + +"Backgrounds" by Jerome Duval (jerome.duval@free.fr) + +(C)2002 OpenBeOS under MIT license + +*/ + +#include "BGWindow.h" + +BGWindow::BGWindow(BRect frame, bool standalone) + : BWindow(frame, WINDOW_TITLE, B_TITLED_WINDOW, + B_NOT_RESIZABLE | B_NOT_ZOOMABLE, B_ALL_WORKSPACES), + fIsStandalone(standalone) +{ + fBGView = new BGView(Bounds(),"BackgroundsView",B_FOLLOW_ALL, B_WILL_DRAW); + AddChild(fBGView); +} + + +bool +BGWindow::QuitRequested() +{ + fBGView->SaveSettings(); + if(fIsStandalone) + be_app->PostMessage(B_QUIT_REQUESTED); + return(true); +} + + +void +BGWindow::WorkspaceActivated(int32 oldWorkspaces, bool active) +{ + fBGView->WorkspaceActivated(oldWorkspaces, active); +} + + +void +BGWindow::ProcessRefs(entry_ref dir_ref, BMessage* msg) +{ + fBGView->ProcessRefs(dir_ref, msg); +} diff --git a/src/prefs/backgrounds/BGWindow.h b/src/prefs/backgrounds/BGWindow.h new file mode 100644 index 0000000000..2112acedf0 --- /dev/null +++ b/src/prefs/backgrounds/BGWindow.h @@ -0,0 +1,31 @@ +/* + +"Backgrounds" by Jerome Duval (jerome.duval@free.fr) + +(C)2002 OpenBeOS under MIT license + +*/ + +#ifndef BG_WINDOW_H +#define BG_WINDOW_H + +#include +#include +#include "BGView.h" + +#define WINDOW_TITLE "Backgrounds" + +class BGWindow : public BWindow +{ +public: + BGWindow(BRect frame, bool standalone = true); + BGView *GetView() {return fBGView;} + void ProcessRefs(entry_ref dir_ref, BMessage* msg); +protected: + virtual bool QuitRequested(); + virtual void WorkspaceActivated(int32 oldWorkspaces, bool active); + BGView *fBGView; + bool fIsStandalone; +}; + +#endif diff --git a/src/prefs/backgrounds/BackgroundImage.cpp b/src/prefs/backgrounds/BackgroundImage.cpp new file mode 100644 index 0000000000..9ecdc93d4b --- /dev/null +++ b/src/prefs/backgrounds/BackgroundImage.cpp @@ -0,0 +1,494 @@ +/* +Open Tracker License + +Terms and Conditions + +Copyright (c) 1991-2000, Be Incorporated. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice applies to all licensees +and shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Be Incorporated shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from Be Incorporated. + +Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks +of Be Incorporated in the United States and other countries. Other brand product +names are registered trademarks or trademarks of their respective holders. +All rights reserved. +*/ + +// Classes used for setting up and managing background images +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "BGView.h" +#include "BackgroundImage.h" + +const char *kBackgroundImageInfo = "be:bgndimginfo"; +const char *kBackgroundImageInfoOffset = "be:bgndimginfooffset"; +const char *kBackgroundImageInfoEraseText = "be:bgndimginfoerasetext"; +const char *kBackgroundImageInfoMode = "be:bgndimginfomode"; +const char *kBackgroundImageInfoWorkspaces = "be:bgndimginfoworkspaces"; +const char *kBackgroundImageInfoPath = "be:bgndimginfopath"; +const char *kBackgroundImageInfoSet = "be:bgndimginfoset"; +const char *kBackgroundImageInfoCacheMode = "be:bgndimginfocachemode"; +const char *kBackgroundImageSetPeriod = "be:bgndimgsetperiod"; +const char *kBackgroundImageRandomChange = "be:bgndimgrandomchange"; +const char *kBackgroundImageCacheMode = "be:bgndimgcachemode"; + +BackgroundImage * +BackgroundImage::GetBackgroundImage(const BNode *node, bool isDesktop, + BGView* view) +{ + BackgroundImage *result = new BackgroundImage(node, isDesktop); + result->bgView = view; + attr_info info; + if (node->GetAttrInfo(kBackgroundImageInfo, &info) != B_OK) + return result; + + BMessage container; + char *buffer = new char [info.size]; + + status_t error = node->ReadAttr(kBackgroundImageInfo, info.type, 0, buffer, + (size_t)info.size); + if (error == info.size) + error = container.Unflatten(buffer); + + delete [] buffer; + + if (error != B_OK) + return NULL; + + container.PrintToStream(); + + uint32 imageSetPeriod = 0; + uint32 globalCacheMode = 0; + bool randomChange = false; + uint32 maxImageSet = 0; + + if(isDesktop) { + container.FindInt32(kBackgroundImageSetPeriod, (int32 *)&imageSetPeriod); + container.FindInt32(kBackgroundImageCacheMode, (int32 *)&globalCacheMode); + container.FindBool(kBackgroundImageRandomChange, &randomChange); + } + + for (int32 index = 0; ; index++) { + const char *path; + uint32 workspaces = B_ALL_WORKSPACES; + Mode mode = kTiled; + bool eraseTextWidgetBackground = true; + BPoint offset; + uint32 imageSet = 0; + uint32 cacheMode = 0; + if (container.FindString(kBackgroundImageInfoPath, index, &path) != B_OK) + break; + + BPath bpath(path); + int32 imageIndex = view->AddImage(bpath); + if(imageIndex < 0) + imageIndex = -imageIndex - 1; + + container.FindInt32(kBackgroundImageInfoWorkspaces, index, + (int32 *)&workspaces); + container.FindInt32(kBackgroundImageInfoMode, index, (int32 *)&mode); + container.FindBool(kBackgroundImageInfoEraseText, index, + &eraseTextWidgetBackground); + container.FindPoint(kBackgroundImageInfoOffset, index, &offset); + if(isDesktop) + { + container.FindInt32(kBackgroundImageInfoSet, index, + (int32 *)&imageSet); + container.FindInt32(kBackgroundImageInfoCacheMode, index, + (int32 *)&cacheMode); + } + + BackgroundImage::BackgroundImageInfo *imageInfo = new + BackgroundImage::BackgroundImageInfo(workspaces, imageIndex, + mode, offset, eraseTextWidgetBackground, imageSet, cacheMode); + + //imageInfo->UnloadBitmap(globalCacheMode); + + if(imageSet > maxImageSet) + maxImageSet = imageSet; + + + + result->Add(imageInfo); + } + + if(result) { + result->fImageSetCount = maxImageSet + 1; + result->fRandomChange = randomChange; + result->fImageSetPeriod = imageSetPeriod; + result->fCacheMode = globalCacheMode; + if(result->fImageSetCount > 1) + result->fShowingImageSet = random()%result->fImageSetCount; + } + + return result; +} + + +BackgroundImage::BackgroundImageInfo::BackgroundImageInfo(uint32 workspaces, + int32 imageIndex, Mode mode, BPoint offset, bool eraseTextWidget, + uint32 imageSet, uint32 cacheMode) + : fWorkspace(workspaces), + fImageIndex(imageIndex), + fMode(mode), + fOffset(offset), + fEraseTextWidgetBackground(eraseTextWidget), + fImageSet(imageSet), + fCacheMode(cacheMode) +{ +} + + +BackgroundImage::BackgroundImageInfo::~BackgroundImageInfo() +{ +} + + +BackgroundImage::BackgroundImage(const BNode *node, bool desktop) + : fIsDesktop(desktop), + fDefinedByNode(*node), + fView(NULL), + fShowingBitmap(NULL), + fBitmapForWorkspaceList(1, true), + fImageSetPeriod(0), + fShowingImageSet(0), + fImageSetCount(0), + fCacheMode(0), + fRandomChange(false) +{ + +} + + +BackgroundImage::~BackgroundImage() +{ +} + + +void +BackgroundImage::Add(BackgroundImageInfo *info) +{ + fBitmapForWorkspaceList.AddItem(info); +} + + +void +BackgroundImage::RemoveAll() +{ + for (int32 index = 0; index < fBitmapForWorkspaceList.CountItems();) { + BackgroundImageInfo *info = fBitmapForWorkspaceList.ItemAt(index); + if(info->fImageSet != fShowingImageSet) + index++; + else + fBitmapForWorkspaceList.RemoveItemAt(index); + } +} + + +void +BackgroundImage::Show(BView *view, int32 workspace) +{ + fView = view; + + BackgroundImageInfo *info = ImageInfoForWorkspace(workspace); + if (info) { + /*BPoseView *poseView = dynamic_cast(fView); + if (poseView) + poseView->SetEraseWidgetTextBackground(info->fEraseTextWidgetBackground);*/ + Show(info, fView); + + } +} + + +void +BackgroundImage::Show(BackgroundImageInfo *info, BView *view) +{ + BBitmap *bitmap = bgView->GetImage(info->fImageIndex)->GetBitmap(); + + if(!bitmap) + return; + + BRect viewBounds(view->Bounds()); + + display_mode mode; + BScreen().GetMode(&mode); + float x_ratio = viewBounds.Width() / mode.virtual_width; + float y_ratio = viewBounds.Height() / mode.virtual_height; + + BRect bitmapBounds(bitmap->Bounds()); + BRect destinationBitmapBounds(bitmapBounds); + destinationBitmapBounds.right *= x_ratio; + destinationBitmapBounds.bottom *= y_ratio; + BPoint offset(info->fOffset); + offset.x *= x_ratio; + offset.y *= y_ratio; + + uint32 tile = 0; + uint32 followFlags = B_FOLLOW_TOP | B_FOLLOW_LEFT; + + // figure out the display mode and the destination bounds for the bitmap + switch (info->fMode) { + case kCentered: + if (fIsDesktop) { + destinationBitmapBounds.OffsetBy( + (viewBounds.Width() - destinationBitmapBounds.Width()) / 2, + (viewBounds.Height() - destinationBitmapBounds.Height()) / 2); + break; + } + // else fall thru + case kScaledToFit: + if (fIsDesktop) { + destinationBitmapBounds = viewBounds; + followFlags = B_FOLLOW_ALL; + break; + } + // else fall thru + case kAtOffset: + { + destinationBitmapBounds.OffsetTo(offset); + break; + } + case kTiled: + // Original Backgrounds Preferences center the tiled paper but the Tracker don't do that + //if (fIsDesktop) { + destinationBitmapBounds.OffsetBy( + (viewBounds.Width() - destinationBitmapBounds.Width()) / 2, + (viewBounds.Height() - destinationBitmapBounds.Height()) / 2); + //} + tile = B_TILE_BITMAP; + break; + } + + // switch to the bitmap and force a redraw + view->SetViewBitmap(bitmap, bitmapBounds, destinationBitmapBounds, + followFlags, tile); + view->Invalidate(); + + /*if(fShowingBitmap != info) { + if(fShowingBitmap) + fShowingBitmap->UnloadBitmap(fCacheMode); + fShowingBitmap = info; + }*/ +} + + +void +BackgroundImage::Remove() +{ + if (fShowingBitmap) { + fView->ClearViewBitmap(); + fView->Invalidate(); + /*BPoseView *poseView = dynamic_cast(fView); + // make sure text widgets draw the default way, erasing their background + if (poseView) + poseView->SetEraseWidgetTextBackground(true);*/ + } + fShowingBitmap = NULL; +} + + +BackgroundImage::BackgroundImageInfo * +BackgroundImage::ImageInfoForWorkspace(int32 workspace) const +{ + uint32 workspaceMask = 1; + + for ( ; workspace; workspace--) + workspaceMask *= 2; + + int32 count = fBitmapForWorkspaceList.CountItems(); + + // do a simple lookup for the most likely candidate bitmap - + // pick the imageInfo that is only defined for this workspace over one + // that supports multiple workspaces + BackgroundImageInfo *result = NULL; + for (int32 index = 0; index < count; index++) { + BackgroundImageInfo *info = fBitmapForWorkspaceList.ItemAt(index); + if(info->fImageSet != fShowingImageSet) + continue; + if(fIsDesktop) { + if (info->fWorkspace == workspaceMask) + return info; + if (info->fWorkspace & workspaceMask) + result = info; + } else + return info; + } + + return result; +} + + +void +BackgroundImage::WorkspaceActivated(BView *view, int32 workspace, bool state) +{ + if (!fIsDesktop) + // we only care for desktop bitmaps + return; + + if (!state) + // we only care comming into a new workspace, not leaving one + return; + + BackgroundImageInfo *info = ImageInfoForWorkspace(workspace); + if (info != fShowingBitmap) { + if (info) + Show(info, view); + else { + /*if (BPoseView *poseView = dynamic_cast(view)) + poseView->SetEraseWidgetTextBackground(true);*/ + view->ClearViewBitmap(); + view->Invalidate(); + } + fShowingBitmap = info; + } +} + + +void +BackgroundImage::ScreenChanged(BRect, color_space) +{ + if (!fIsDesktop || !fShowingBitmap) + return; + + /*if (fShowingBitmap->fMode == kCentered) { + BRect viewBounds(fView->Bounds()); + BRect bitmapBounds(fShowingBitmap->fBitmap->Bounds()); + BRect destinationBitmapBounds(bitmapBounds); + destinationBitmapBounds.OffsetBy( + (viewBounds.Width() - bitmapBounds.Width()) / 2, + (viewBounds.Height() - bitmapBounds.Height()) / 2); + + fView->SetViewBitmap(fShowingBitmap->fBitmap, bitmapBounds, destinationBitmapBounds, + B_FOLLOW_NONE, 0); + fView->Invalidate(); + }*/ +} + + +status_t +BackgroundImage::SetBackgroundImage(BNode *node) +{ + status_t err; + BMessage container; + int32 count = fBitmapForWorkspaceList.CountItems(); + + for (int32 index = 0; index < count; index++) { + BackgroundImageInfo *info = fBitmapForWorkspaceList.ItemAt(index); + if(bgView->GetImage(info->fImageIndex)==NULL) + continue; + + container.AddBool(kBackgroundImageInfoEraseText, info->fEraseTextWidgetBackground); + container.AddString( kBackgroundImageInfoPath, bgView->GetImage(info->fImageIndex)->GetPath().Path()); + container.AddInt32( kBackgroundImageInfoWorkspaces, info->fWorkspace); + container.AddPoint( kBackgroundImageInfoOffset, info->fOffset); + container.AddInt32( kBackgroundImageInfoMode, info->fMode); + if(fIsDesktop) { + container.AddInt32( kBackgroundImageInfoSet, info->fImageSet); + } + } + + container.PrintToStream(); + + char buffer[container.FlattenedSize()]; + if((err = container.Flatten(buffer, container.FlattenedSize())) != B_OK) + return err; + ssize_t size = node->WriteAttr(kBackgroundImageInfo, 0, 0, buffer, container.FlattenedSize()); + if(size <= 0) + return B_ERROR; + return B_OK; +} + + +/*BackgroundImage * +BackgroundImage::Refresh(BackgroundImage *oldBackgroundImage, + const BNode *fromNode, bool desktop, BPoseView *poseView) +{ + if (oldBackgroundImage) { + oldBackgroundImage->Remove(); + delete oldBackgroundImage; + } + + BackgroundImage *result = GetBackgroundImage(fromNode, desktop); + if (result && poseView->ViewMode() != kListMode) + result->Show(poseView, current_workspace()); + return result; +} + + +void +BackgroundImage::ChangeImageSet(BPoseView *poseView) +{ + if(fRandomChange) { + if(fImageSetCount > 1) { + uint32 oldShowingImageSet = fShowingImageSet; + while(oldShowingImageSet == fShowingImageSet) + fShowingImageSet = random()%fImageSetCount; + } else + fShowingImageSet = 0; + } else { + fShowingImageSet++; + if(fShowingImageSet > fImageSetCount - 1) + fShowingImageSet = 0; + } + + this->Show(poseView, current_workspace()); +}*/ + + +Image::Image(BPath path) + : fBitmap(NULL), + fPath(path) +{ + name = path.Leaf(); +} + + +Image::~Image() +{ + if(fBitmap!=NULL) { + delete fBitmap; + fBitmap = NULL; + } +} + + +BBitmap* +Image::GetBitmap() +{ + if(!fBitmap) + fBitmap = BTranslationUtils::GetBitmap(fPath.Path()); + return fBitmap; +} diff --git a/src/prefs/backgrounds/BackgroundImage.h b/src/prefs/backgrounds/BackgroundImage.h new file mode 100644 index 0000000000..c49e8192e2 --- /dev/null +++ b/src/prefs/backgrounds/BackgroundImage.h @@ -0,0 +1,171 @@ +/* +Open Tracker License + +Terms and Conditions + +Copyright (c) 1991-2000, Be Incorporated. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice applies to all licensees +and shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Be Incorporated shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from Be Incorporated. + +Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks +of Be Incorporated in the United States and other countries. Other brand product +names are registered trademarks or trademarks of their respective holders. +All rights reserved. +*/ + +// Classes used for setting up and managing background images +// + +#ifndef __BACKGROUND_IMAGE__ +#define __BACKGROUND_IMAGE__ + +#include "String.h" +#include "ObjectList.h" +#include +#include + + +class BView; +class BBitmap; + +class BackgroundImage; +class Image; +class BGView; + +extern const char *kBackgroundImageInfo; +extern const char *kBackgroundImageInfoOffset; +extern const char *kBackgroundImageInfoEraseText; +extern const char *kBackgroundImageInfoMode; +extern const char *kBackgroundImageInfoWorkspaces; +extern const char *kBackgroundImageInfoPath; +extern const char *kBackgroundImageInfoSet; +extern const char *kBackgroundImageInfoSetPeriod; + +const uint32 kRestoreBackgroundImage = 'Tbgr'; +const uint32 kChangeBackgroundImage = 'Cbgr'; + +class BackgroundImage { + // This class knows everything about which bitmap to use for a given + // view and how. + // Unlike other windows, the Desktop window can have different backgrounds + // for each workspace +public: + + enum Mode { + kAtOffset, + kCentered, // only works on Desktop + kScaledToFit, // only works on Desktop + kTiled + }; + + class BackgroundImageInfo { + // element of the per-workspace list + public: + BackgroundImageInfo(uint32 workspace, int32 imageIndex, Mode mode, + BPoint offset, bool eraseTextWidget, uint32 imageSet, + uint32 cacheMode); + ~BackgroundImageInfo(); + + void LoadBitmap(); + void UnloadBitmap(uint32 globalCacheMode); + + uint32 fWorkspace; + int32 fImageIndex; + Mode fMode; + BPoint fOffset; + bool fEraseTextWidgetBackground; + uint32 fImageSet; + uint32 fCacheMode; // image cache strategy (0 cache , 1 no cache) + }; + + + + static BackgroundImage *GetBackgroundImage(const BNode *, bool isDesktop, + BGView* view); + // create a BackgroundImage object by reading it from a node + virtual ~BackgroundImage(); + + void Show(BView *view, int32 workspace); + // display the right background for a given workspace + void Remove(); + // remove the background from it's current view + + void WorkspaceActivated(BView *view, int32 workspace, bool state); + // respond to a workspace change + void ScreenChanged(BRect , color_space); + // respond to a screen size change + /*static BackgroundImage *Refresh(BackgroundImage *oldBackgroundImage, + const BNode *fromNode, bool desktop, BPoseView *poseView); + // respond to a background image setting change + void ChangeImageSet(BPoseView *poseView); + // change to the next imageSet if any, no refresh*/ + BackgroundImageInfo *ImageInfoForWorkspace(int32) const; + + // return fIsDesktop + bool IsDesktop() { return fIsDesktop;} + + status_t SetBackgroundImage(BNode *node); + + void Show(BackgroundImageInfo *, BView *view); + + uint32 GetShowingImageSet() {return fShowingImageSet;} + + void Add(BackgroundImageInfo *); + void RemoveAll(); + +private: + BackgroundImage(const BNode *, bool); + // no public constructor, GetBackgroundImage factory function is + // used instead + + bool fIsDesktop; + BNode fDefinedByNode; + BView *fView; + BGView* bgView; + BackgroundImageInfo *fShowingBitmap; + + BObjectList fBitmapForWorkspaceList; + + uint32 fImageSetPeriod; // period between imagesets, 0 if none + uint32 fShowingImageSet; // current imageset + uint32 fImageSetCount; // imageset count + uint32 fCacheMode;// image cache strategy (0 all, 1 none, 2 own strategy) + bool fRandomChange; // random or sequential change +}; + +class Image { + // element for each image + public: + Image(BPath path); + ~Image(); + + void UnloadBitmap(); + const char* GetName() {return name.String();} + BBitmap* GetBitmap(); + BPath GetPath() {return fPath;} + private: + BBitmap *fBitmap; + BPath fPath; + BString name; +}; + +#endif diff --git a/src/prefs/backgrounds/Backgrounds b/src/prefs/backgrounds/Backgrounds new file mode 100755 index 0000000000..a9be78319f Binary files /dev/null and b/src/prefs/backgrounds/Backgrounds differ diff --git a/src/prefs/backgrounds/Backgrounds.rsrc b/src/prefs/backgrounds/Backgrounds.rsrc new file mode 100644 index 0000000000..ed5ff67b32 Binary files /dev/null and b/src/prefs/backgrounds/Backgrounds.rsrc differ diff --git a/src/prefs/backgrounds/Jamfile b/src/prefs/backgrounds/Jamfile new file mode 100644 index 0000000000..15bb68a632 --- /dev/null +++ b/src/prefs/backgrounds/Jamfile @@ -0,0 +1,7 @@ +SubDir OBOS_TOP src prefs backgrounds ; + +AddResources Backgrounds : Backgrounds.rsrc ; + +Preference Backgrounds : BackgroundImage.cpp BGMain.cpp BGView.cpp BGWindow.cpp ; + +LinkSharedOSLibs Backgrounds : be tracker translation ; \ No newline at end of file diff --git a/src/prefs/backgrounds/ObjectList.h b/src/prefs/backgrounds/ObjectList.h new file mode 100644 index 0000000000..cc639c574b --- /dev/null +++ b/src/prefs/backgrounds/ObjectList.h @@ -0,0 +1,800 @@ +/* +Open Tracker License + +Terms and Conditions + +Copyright (c) 1991-2000, Be Incorporated. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice applies to all licensees +and shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Be Incorporated shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from Be Incorporated. + +Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks +of Be Incorporated in the United States and other countries. Other brand product +names are registered trademarks or trademarks of their respective holders. +All rights reserved. +*/ + +/**************************************************************************** +** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ** +** ** +** DANGER, WILL ROBINSON! ** +** ** +** The interfaces contained here are part of BeOS's ** +** ** +** >> PRIVATE NOT FOR PUBLIC USE << ** +** ** +** implementation. ** +** ** +** These interfaces WILL CHANGE in future releases. ** +** If you use them, your app WILL BREAK at some future time. ** +** ** +** (And yes, this does mean that binaries built from OpenTracker will not ** +** be compatible with some future releases of the OS. When that happens, ** +** we will provide an updated version of this file to keep compatibility.) ** +** ** +** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ** +****************************************************************************/ + +// +// ObjectList is a wrapper around BList that adds type safety, +// optional object ownership, search, insert operations, etc. +// + +#ifndef __OBJECT_LIST__ +#define __OBJECT_LIST__ + +#ifndef _BE_H +#include +#endif + +#include + +template class BObjectList; + +template +struct UnaryPredicate { + + virtual int operator()(const T *) const + // virtual could be avoided here if FindBinaryInsertionIndex, + // etc. were member template functions + { return 0; } + +private: + static int _unary_predicate_glue(const void *item, void *context); + +friend class BObjectList; +}; + +template +int +UnaryPredicate::_unary_predicate_glue(const void *item, void *context) +{ + return ((UnaryPredicate *)context)->operator()((const T *)item); +} + + +class _PointerList_ : public BList { +public: + _PointerList_(const _PointerList_ &list); + _PointerList_(int32 itemsPerBlock = 20, bool owning = false); + ~_PointerList_(); + + typedef void *(* GenericEachFunction)(void *, void *); + typedef int (* GenericCompareFunction)(const void *, const void *); + typedef int (* GenericCompareFunctionWithState)(const void *, const void *, + void *); + typedef int (* UnaryPredicateGlue)(const void *, void *); + + void *EachElement(GenericEachFunction, void *); + void SortItems(GenericCompareFunction); + void SortItems(GenericCompareFunctionWithState, void *state); + void HSortItems(GenericCompareFunction); + void HSortItems(GenericCompareFunctionWithState, void *state); + + void *BinarySearch(const void *, GenericCompareFunction) const; + void *BinarySearch(const void *, GenericCompareFunctionWithState, void *state) const; + + int32 BinarySearchIndex(const void *, GenericCompareFunction) const; + int32 BinarySearchIndex(const void *, GenericCompareFunctionWithState, void *state) const; + int32 BinarySearchIndexByPredicate(const void *, UnaryPredicateGlue) const; + + bool Owning() const; + bool ReplaceItem(int32, void *); + +protected: + bool owning; + +}; + +template +class BObjectList : private _PointerList_ { +public: + + // iteration and sorting + typedef T *(* EachFunction)(T *, void *); + typedef const T *(* ConstEachFunction)(const T *, void *); + typedef int (* CompareFunction)(const T *, const T *); + typedef int (* CompareFunctionWithState)(const T *, const T *, void *state); + + BObjectList(int32 itemsPerBlock = 20, bool owning = false); + BObjectList(const BObjectList &list); + // clones list; if list is owning, makes copies of all + // the items + + virtual ~BObjectList(); + + BObjectList &operator=(const BObjectList &list); + // clones list; if list is owning, makes copies of all + // the items + + // adding and removing + // ToDo: + // change Add calls to return const item + bool AddItem(T *); + bool AddItem(T *, int32); + bool AddList(BObjectList *); + bool AddList(BObjectList *, int32); + + bool RemoveItem(T *, bool deleteIfOwning = true); + // if owning, deletes the removed item + T *RemoveItemAt(int32); + // returns the removed item + + void MakeEmpty(); + + // item access + T *ItemAt(int32) const; + + bool ReplaceItem(int32 index, T *); + // if list is owning, deletes the item at first + T *SwapWithItem(int32 index, T *newItem); + // same as ReplaceItem, except does not delete old item at , + // returns it instead + + T *FirstItem() const; + T *LastItem() const; + + // misc. getters + int32 IndexOf(const T *) const; + bool HasItem(const T *) const; + bool IsEmpty() const; + int32 CountItems() const; + + T *EachElement(EachFunction, void *); + const T *EachElement(ConstEachFunction, void *) const; + + void SortItems(CompareFunction); + void SortItems(CompareFunctionWithState, void *state); + void HSortItems(CompareFunction); + void HSortItems(CompareFunctionWithState, void *state); + + // linear search, returns first item that matches predicate + const T *FindIf(const UnaryPredicate &) const; + T *FindIf(const UnaryPredicate &); + + // list must be sorted with CompareFunction for these to work + const T *BinarySearch(const T &, CompareFunction) const; + const T *BinarySearch(const T &, CompareFunctionWithState, void *state) const; + + // Binary insertion - list must be sorted with CompareFunction for + // these to work + + // simple insert + void BinaryInsert(T *, CompareFunction); + void BinaryInsert(T *, CompareFunctionWithState, void *state); + void BinaryInsert(T *, const UnaryPredicate &); + + // unique insert, returns false if item already in list + bool BinaryInsertUnique(T *, CompareFunction); + bool BinaryInsertUnique(T *, CompareFunctionWithState, void *state); + bool BinaryInsertUnique(T *, const UnaryPredicate &); + + // insert a copy of the item, returns new inserted item + T *BinaryInsertCopy(const T ©This, CompareFunction); + T *BinaryInsertCopy(const T ©This, CompareFunctionWithState, void *state); + + // insert a copy of the item if not in list already + // returns new inserted item or existing item in case of a conflict + T *BinaryInsertCopyUnique(const T ©This, CompareFunction); + T *BinaryInsertCopyUnique(const T ©This, CompareFunctionWithState, void *state); + + + int32 FindBinaryInsertionIndex(const UnaryPredicate &, bool *alreadyInList = 0) const; + // returns either the index into which a new item should be inserted + // or index of an existing item that matches the predicate + + // deprecated API, will go away + BList *AsBList() + { return this; } + const BList *AsBList() const + { return this; } +private: + void SetItem(int32, T *); +}; + +template +Result +WhileEachListItem(BObjectList *list, Result (Item::*func)(Param1), Param1 p1) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (list->ItemAt(index)->*func)(p1)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (*func)(Item *, Param1), Param1 p1) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (*func)(list->ItemAt(index), p1)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (Item::*func)(Param1, Param2), + Param1 p1, Param2 p2) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (list->ItemAt(index)->*func)(p1, p2)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (*func)(Item *, Param1, Param2), + Param1 p1, Param2 p2) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (*func)(list->ItemAt(index), p1, p2)) != 0) + break; + + return result; +} + +template +Result +WhileEachListItem(BObjectList *list, Result (*func)(Item *, Param1, Param2, + Param3, Param4), Param1 p1, Param2 p2, Param3 p3, Param4 p4) +{ + Result result = 0; + int32 count = list->CountItems(); + + for (int32 index = 0; index < count; index++) + if ((result = (*func)(list->ItemAt(index), p1, p2, p3, p4)) != 0) + break; + + return result; +} + +template +void +EachListItemIgnoreResult(BObjectList *list, Result (Item::*func)()) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (list->ItemAt(index)->*func)(); +} + +template +void +EachListItem(BObjectList *list, void (*func)(Item *, Param1), Param1 p1) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1); +} + +template +void +EachListItem(BObjectList *list, void (Item::*func)(Param1, Param2), + Param1 p1, Param2 p2) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (list->ItemAt(index)->*func)(p1, p2); +} + +template +void +EachListItem(BObjectList *list, void (*func)(Item *,Param1, Param2), + Param1 p1, Param2 p2) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1, p2); +} + +template +void +EachListItem(BObjectList *list, void (*func)(Item *,Param1, Param2, + Param3), Param1 p1, Param2 p2, Param3 p3) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1, p2, p3); +} + + +template +void +EachListItem(BObjectList *list, void (*func)(Item *,Param1, Param2, + Param3, Param4), Param1 p1, Param2 p2, Param3 p3, Param4 p4) +{ + int32 count = list->CountItems(); + for (int32 index = 0; index < count; index++) + (func)(list->ItemAt(index), p1, p2, p3, p4); +} + +// inline code + +inline bool +_PointerList_::Owning() const +{ + return owning; +} + +template +BObjectList::BObjectList(int32 itemsPerBlock, bool owning) + : _PointerList_(itemsPerBlock, owning) +{ +} + +template +BObjectList::BObjectList(const BObjectList &list) + : _PointerList_(list) +{ + owning = list.owning; + if (owning) { + // make our own copies in an owning list + int32 count = list.CountItems(); + for (int32 index = 0; index < count; index++) { + T *item = list.ItemAt(index); + if (item) + item = new T(*item); + SetItem(index, item); + } + } +} + +template +BObjectList::~BObjectList() +{ + if (Owning()) + // have to nuke elements first + MakeEmpty(); + +} + +template +BObjectList & +BObjectList::operator=(const BObjectList &list) +{ + owning = list.owning; + BObjectList &result = (BObjectList &)_PointerList_::operator=(list); + if (owning) { + // make our own copies in an owning list + int32 count = list.CountItems(); + for (int32 index = 0; index < count; index++) { + T *item = list.ItemAt(index); + if (item) + item = new T(*item); + SetItem(index, item); + } + } + return result; +} + +template +bool +BObjectList::AddItem(T *item) +{ + // need to cast to void * to make T work for const pointers + return _PointerList_::AddItem((void *)item); +} + +template +bool +BObjectList::AddItem(T *item, int32 atIndex) +{ + return _PointerList_::AddItem((void *)item, atIndex); +} + +template +bool +BObjectList::AddList(BObjectList *newItems) +{ + return _PointerList_::AddList(newItems); +} + +template +bool +BObjectList::AddList(BObjectList *newItems, int32 atIndex) +{ + return _PointerList_::AddList(newItems, atIndex); +} + + +template +bool +BObjectList::RemoveItem(T *item, bool deleteIfOwning) +{ + bool result = _PointerList_::RemoveItem((void *)item); + + if (result && Owning() && deleteIfOwning) + delete item; + + return result; +} + +template +T * +BObjectList::RemoveItemAt(int32 index) +{ + return (T *)_PointerList_::RemoveItem(index); +} + +template +inline T * +BObjectList::ItemAt(int32 index) const +{ + return (T *)_PointerList_::ItemAt(index); +} + +template +bool +BObjectList::ReplaceItem(int32 index, T *item) +{ + if (owning) + delete ItemAt(index); + return _PointerList_::ReplaceItem(index, (void *)item); +} + +template +T * +BObjectList::SwapWithItem(int32 index, T *newItem) +{ + T *result = ItemAt(index); + _PointerList_::ReplaceItem(index, (void *)newItem); + return result; +} + +template +void +BObjectList::SetItem(int32 index, T *newItem) +{ + _PointerList_::ReplaceItem(index, (void *)newItem); +} + +template +int32 +BObjectList::IndexOf(const T *item) const +{ + return _PointerList_::IndexOf((void *)item); +} + +template +T * +BObjectList::FirstItem() const +{ + return (T *)_PointerList_::FirstItem(); +} + +template +T * +BObjectList::LastItem() const +{ + return (T *)_PointerList_::LastItem(); +} + +template +bool +BObjectList::HasItem(const T *item) const +{ + return _PointerList_::HasItem((void *)item); +} + +template +bool +BObjectList::IsEmpty() const +{ + return _PointerList_::IsEmpty(); +} + +template +int32 +BObjectList::CountItems() const +{ + return _PointerList_::CountItems(); +} + +template +void +BObjectList::MakeEmpty() +{ + if (owning) { + int32 count = CountItems(); + for (int32 index = 0; index < count; index++) + delete ItemAt(index); + } + _PointerList_::MakeEmpty(); +} + +template +T * +BObjectList::EachElement(EachFunction func, void *params) +{ + return (T *)_PointerList_::EachElement((GenericEachFunction)func, params); +} + + +template +const T * +BObjectList::EachElement(ConstEachFunction func, void *params) const +{ + return (const T *) + const_cast *>(this)->_PointerList_::EachElement( + (GenericEachFunction)func, params); +} + +template +const T * +BObjectList::FindIf(const UnaryPredicate &predicate) const +{ + int32 count = CountItems(); + for (int32 index = 0; index < count; index++) + if (predicate.operator()(ItemAt(index)) == 0) + return ItemAt(index); + return 0; +} + +template +T * +BObjectList::FindIf(const UnaryPredicate &predicate) +{ + int32 count = CountItems(); + for (int32 index = 0; index < count; index++) + if (predicate.operator()(ItemAt(index)) == 0) + return ItemAt(index); + return 0; +} + + +template +void +BObjectList::SortItems(CompareFunction function) +{ + _PointerList_::SortItems((GenericCompareFunction)function); +} + +template +void +BObjectList::SortItems(CompareFunctionWithState function, void *state) +{ + _PointerList_::SortItems((GenericCompareFunctionWithState)function, state); +} + +template +void +BObjectList::HSortItems(CompareFunction function) +{ + _PointerList_::HSortItems((GenericCompareFunction)function); +} + +template +void +BObjectList::HSortItems(CompareFunctionWithState function, void *state) +{ + _PointerList_::HSortItems((GenericCompareFunctionWithState)function, state); +} + +template +const T * +BObjectList::BinarySearch(const T &key, CompareFunction func) const +{ + return (const T *)_PointerList_::BinarySearch(&key, + (GenericCompareFunction)func); +} + +template +const T * +BObjectList::BinarySearch(const T &key, CompareFunctionWithState func, void *state) const +{ + return (const T *)_PointerList_::BinarySearch(&key, + (GenericCompareFunctionWithState)func, state); +} + +template +void +BObjectList::BinaryInsert(T *item, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunction)func); + if (index >= 0) + // already in list, add after existing + AddItem(item, index + 1); + else + AddItem(item, -index - 1); +} + +template +void +BObjectList::BinaryInsert(T *item, CompareFunctionWithState func, void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunctionWithState)func, state); + if (index >= 0) + // already in list, add after existing + AddItem(item, index + 1); + else + AddItem(item, -index - 1); +} + +template +bool +BObjectList::BinaryInsertUnique(T *, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunction)func); + if (index >= 0) + return false; + + AddItem(item, -index - 1); + return true; +} + +template +bool +BObjectList::BinaryInsertUnique(T *, CompareFunctionWithState func, void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(item, + (GenericCompareFunctionWithState)func, state); + if (index >= 0) + return false; + + AddItem(item, -index - 1); + return true; +} + + +template +T * +BObjectList::BinaryInsertCopy(const T ©This, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunction)func); + + if (index >= 0) + index++; + else + index = -index - 1; + + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +T * +BObjectList::BinaryInsertCopy(const T ©This, CompareFunctionWithState func, void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunctionWithState)func, state); + + if (index >= 0) + index++; + else + index = -index - 1; + + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +T * +BObjectList::BinaryInsertCopyUnique(const T ©This, CompareFunction func) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunction)func); + if (index >= 0) + return ItemAt(index); + + index = -index - 1; + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +T * +BObjectList::BinaryInsertCopyUnique(const T ©This, CompareFunctionWithState func, + void *state) +{ + int32 index = _PointerList_::BinarySearchIndex(©This, + (GenericCompareFunctionWithState)func, state); + if (index >= 0) + return ItemAt(index); + + index = -index - 1; + T *newItem = new T(copyThis); + AddItem(newItem, index); + return newItem; +} + +template +int32 +BObjectList::FindBinaryInsertionIndex(const UnaryPredicate &pred, bool *alreadyInList) + const +{ + int32 index = _PointerList_::BinarySearchIndexByPredicate(&pred, + (UnaryPredicateGlue)&UnaryPredicate::_unary_predicate_glue); + + if (alreadyInList) + *alreadyInList = index >= 0; + + if (index < 0) + index = -index - 1; + + return index; +} + +template +void +BObjectList::BinaryInsert(T *item, const UnaryPredicate &pred) +{ + int32 index = FindBinaryInsertionIndex(pred); + AddItem(item, index); +} + +template +bool +BObjectList::BinaryInsertUnique(T *item, const UnaryPredicate &pred) +{ + bool alreadyInList; + int32 index = FindBinaryInsertionIndex(pred, &alreadyInList); + if (alreadyInList) + return false; + + AddItem(item, index); + return true; +} + + +#endif