├── .github └── workflows │ └── build.yaml ├── .gitignore ├── DocumentViewer.hvif ├── DocumentViewerScreenshot.png ├── README.md ├── application ├── BaseEngine.cpp ├── BaseEngine.h ├── BookmarksView.cpp ├── BookmarksView.h ├── CircleMenuView.cpp ├── CircleMenuView.h ├── DJVUEngine.cpp ├── DJVUEngine.h ├── Debug.h ├── DocumentView.cpp ├── DocumentView.h ├── DocumentViewer.rdef ├── DocumentViewer_icon.png ├── Flags.h ├── Icons.rdef ├── ImageButton.cpp ├── ImageButton.h ├── ImagePopUp.cpp ├── ImagePopUp.h ├── ImageSpinner.cpp ├── ImageSpinner.h ├── ImageTabView.cpp ├── ImageTabView.h ├── MainApplication.h ├── MainWindow.cpp ├── MainWindow.h ├── MainWindowRB.cpp ├── MainWindowRB.h ├── Makefile ├── Messages.h ├── NumberControl.cpp ├── NumberControl.h ├── OutlineView.cpp ├── OutlineView.h ├── PDFEngine.cpp ├── PDFEngine.h ├── PDFFilter.cpp ├── PDFFilter.h ├── PageNavigationView.cpp ├── PageNavigationView.h ├── PasswordRequestWindow.cpp ├── PasswordRequestWindow.h ├── PreviewView.cpp ├── PreviewView.h ├── PrintPreviewView.cpp ├── PrintPreviewView.h ├── PrintingWindow.cpp ├── PrintingWindow.h ├── SearchView.cpp ├── SearchView.h ├── Settings.h ├── Timer.h ├── Tools.h └── main.cpp └── documentation ├── help.odt └── help.pdf /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: "haiku-ci" 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | build-haiku: 6 | timeout-minutes: 60 7 | runs-on: ${{ matrix.config.runner }} 8 | name: build-${{ matrix.config.os }}-${{ matrix.config.version }}-${{ matrix.config.architecture }} 9 | 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | config: 14 | # The OS versions supported are specific to the version of the action 15 | # https://github.com/cross-platform-actions/action/blob/master/changelog.md 16 | - { os: haiku, version: 'r1beta5', runner: 'ubuntu-latest', architecture: 'x86-64' } 17 | - { os: haiku, version: 'r1beta5', runner: 'ubuntu-latest', architecture: 'x86' } 18 | - { os: haiku, version: 'nightly', runner: 'ubuntu-latest', architecture: 'x86-64' } 19 | - { os: haiku, version: 'nightly', runner: 'ubuntu-latest', architecture: 'x86' } 20 | 21 | steps: 22 | - uses: actions/checkout@v4 23 | 24 | - uses: korli/action@v0.25.0-haiku3 25 | with: 26 | operating_system: ${{ matrix.config.os }} 27 | version: ${{ matrix.config.version }} 28 | architecture: ${{ matrix.config.architecture }} 29 | run: | 30 | if [[ `uname -m` == BePC ]]; then 31 | ssh user@localhost "pkgman update -y haiku_x86_devel devel:libdjvulibre_x86 devel:libfreetype_x86 devel:libjbig2dec_x86 devel:libjpeg_x86 devel:libmupdf_x86 devel:libopenjp2_x86 devel:libz_x86 cmd:gcc_x86 gcc_x86_syslibs_devel cmd:as_x86" && 32 | cd application && setarch x86 make 33 | else 34 | ssh user@localhost "pkgman update -y haiku_devel devel:libdjvulibre devel:libfreetype devel:libjbig2dec devel:libjpeg devel:libmupdf devel:libopenjp2 devel:libz cmd:gcc gcc_syslibs_devel cmd:as" && 35 | cd application && make 36 | fi 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | objects*/ 2 | -------------------------------------------------------------------------------- /DocumentViewer.hvif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HaikuArchives/DocumentViewer/963d1176cdfe9aab945531633f01334eaac0a686/DocumentViewer.hvif -------------------------------------------------------------------------------- /DocumentViewerScreenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HaikuArchives/DocumentViewer/963d1176cdfe9aab945531633f01334eaac0a686/DocumentViewerScreenshot.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | DocumentViewer 2 | = 3 | 4 | DocumentViewer is a viewer supporting PDF and DJVU files. 5 | It provides many features, making it easy to open and view documents.
6 | 7 | 8 | 9 | ## Features include: 10 | * Printing 11 | * A view panel 12 | * Zooming in and out 13 | * Fitting the page length or width 14 | * Thumbnails 15 | * Text search 16 | * A home panel giving access to more features 17 | * Offline user documentation 18 | -------------------------------------------------------------------------------- /application/BaseEngine.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2012 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #include "BaseEngine.h" 10 | 11 | #include "Flags.h" 12 | #include "Messages.h" 13 | 14 | using namespace std; 15 | 16 | pthread_mutex_t BaseEngine::gEngineStopMutex = PTHREAD_MUTEX_INITIALIZER; 17 | pthread_mutex_t BaseEngine::gTextSearchStopMutex = PTHREAD_MUTEX_INITIALIZER; 18 | 19 | BaseEngine::BaseEngine(void) 20 | : 21 | fStopThread(false), 22 | fZoomFactor(1), 23 | fPages(0), 24 | fRotation(0), 25 | fForwardCache(16), 26 | fBackwardCache(16), 27 | fCurrentPageNo(0), 28 | fSearchFlag(0), 29 | fDefaultRect(0, 0, 300, 500), 30 | fHighlightUnderText(false), 31 | fStopTextSearchThread(false) 32 | { 33 | fTextSearchThread = nullptr; 34 | fDrawingThread = nullptr; 35 | } 36 | 37 | 38 | BaseEngine::~BaseEngine() 39 | { 40 | StopTextSearch(); 41 | 42 | for (std::pair< BBitmap*, bool> bitmap : fBitmap) { 43 | if (bitmap.first != nullptr) { 44 | delete bitmap.first; 45 | bitmap.first = nullptr; 46 | } 47 | } 48 | } 49 | 50 | 51 | void 52 | BaseEngine::Start(void) 53 | { 54 | fPages = PageCount(); 55 | 56 | fBitmap.resize(fPages, std::pair((BBitmap*)nullptr, false)); 57 | 58 | fMutex.resize(fPages); 59 | for (int i = 0; i < fPages; i++) 60 | pthread_mutex_init(&fMutex[i], NULL); 61 | 62 | pthread_create(&fDrawingThread, nullptr, _DrawingThread, (void*)(this)); 63 | } 64 | 65 | 66 | void 67 | BaseEngine::Stop(void) 68 | { 69 | pthread_mutex_lock(&gEngineStopMutex); 70 | fStopThread = true; 71 | pthread_mutex_unlock(&gEngineStopMutex); 72 | 73 | while (true) { 74 | usleep(1000); 75 | pthread_mutex_lock(&gEngineStopMutex); 76 | if (fStopThread == false) { 77 | pthread_mutex_unlock(&gEngineStopMutex); 78 | break; 79 | } 80 | pthread_mutex_unlock(&gEngineStopMutex); 81 | } 82 | } 83 | 84 | 85 | void* 86 | BaseEngine::_DrawingThread(void* arg) 87 | { 88 | rename_thread(find_thread(NULL), "_DrawingThread"); 89 | 90 | BaseEngine* engine =(BaseEngine*)arg; 91 | int& pages = engine->fPages; 92 | std::vector< std::pair >& bitmap = engine->fBitmap; 93 | std::vector< pthread_mutex_t >& mutex = engine->fMutex; 94 | 95 | int upperbound = -1; 96 | int lowerbound = -1; 97 | int pageFuture = -1; 98 | int pagePast = -1; 99 | int currentPage = -1; 100 | int deleteIndex = 0; 101 | bool forwardPriority = true; 102 | 103 | while(true) { 104 | pthread_mutex_lock(&gEngineStopMutex); 105 | if (engine->fStopThread) { 106 | engine->fStopThread = false; 107 | pthread_mutex_unlock(&gEngineStopMutex); 108 | return nullptr; 109 | } 110 | pthread_mutex_unlock(&gEngineStopMutex); 111 | 112 | if (currentPage != engine->fCurrentPageNo) { 113 | if (engine->fCurrentPageNo < currentPage) 114 | forwardPriority = false; 115 | else 116 | forwardPriority = true; 117 | 118 | deleteIndex = 0; 119 | currentPage = engine->fCurrentPageNo; 120 | pageFuture = pagePast = currentPage; 121 | lowerbound = currentPage - engine->fBackwardCache; 122 | upperbound = currentPage + engine->fForwardCache; 123 | 124 | if (lowerbound < 0) lowerbound = 0; 125 | if (upperbound >= pages) upperbound = pages - 1; 126 | } else { 127 | for (; deleteIndex < pages; ++deleteIndex) { 128 | pthread_mutex_lock(&mutex[deleteIndex]); 129 | if (bitmap[deleteIndex].first != nullptr 130 | && (deleteIndex < lowerbound || deleteIndex > upperbound)) { 131 | delete bitmap[deleteIndex].first; 132 | bitmap[deleteIndex].first = nullptr; 133 | pthread_mutex_unlock(&mutex[deleteIndex]); 134 | break; 135 | } 136 | pthread_mutex_unlock(&mutex[deleteIndex]); 137 | } 138 | 139 | if (forwardPriority) { 140 | if (pageFuture < upperbound) { 141 | ++pageFuture; 142 | pthread_mutex_lock(&mutex[pageFuture]); 143 | if (bitmap[pageFuture].first == nullptr) { 144 | bitmap[pageFuture] = engine->_RenderBitmap(pageFuture); 145 | } else if (bitmap[pageFuture].second == true) { 146 | delete bitmap[pageFuture].first; 147 | bitmap[pageFuture] = engine->_RenderBitmap(pageFuture); 148 | } 149 | pthread_mutex_unlock(&mutex[pageFuture]); 150 | } else if (pagePast > lowerbound) { 151 | --pagePast; 152 | pthread_mutex_lock(&mutex[pagePast]); 153 | if (bitmap[pagePast].first == nullptr) { 154 | bitmap[pagePast] = engine->_RenderBitmap(pagePast); 155 | } else if (bitmap[pageFuture].second == true) { 156 | delete bitmap[pageFuture].first; 157 | bitmap[pageFuture] = engine->_RenderBitmap(pageFuture); 158 | } 159 | pthread_mutex_unlock(&mutex[pagePast]); 160 | } else { 161 | usleep(1000); 162 | } 163 | } else { 164 | if (pagePast > lowerbound) { 165 | --pagePast; 166 | pthread_mutex_lock(&mutex[pagePast]); 167 | if (bitmap[pagePast].first == nullptr) 168 | bitmap[pagePast] = engine->_RenderBitmap(pagePast); 169 | 170 | pthread_mutex_unlock(&mutex[pagePast]); 171 | } else if (pageFuture < upperbound) { 172 | ++pageFuture; 173 | pthread_mutex_lock(&mutex[pageFuture]); 174 | if (bitmap[pageFuture].first == nullptr) 175 | bitmap[pageFuture] = engine->_RenderBitmap(pageFuture); 176 | 177 | pthread_mutex_unlock(&mutex[pageFuture]); 178 | } else { 179 | usleep(1000); 180 | } 181 | } 182 | } 183 | } 184 | return nullptr; 185 | } 186 | 187 | 188 | int const& 189 | BaseEngine::PageRotation(int pageNumber) 190 | { 191 | return fRotation; 192 | } 193 | 194 | 195 | void 196 | BaseEngine::SetZoom(float zoomFactor) 197 | { 198 | if (fZoomFactor == zoomFactor) 199 | return; 200 | 201 | fZoomFactor = zoomFactor; 202 | fDefaultRect.right = 300 * fZoomFactor; 203 | fDefaultRect.bottom = 500 * fZoomFactor; 204 | 205 | // Mark all existing bitmap as dirty as they need to be rendered again. 206 | for (int i = 0; i < fPages; ++i) 207 | if (fBitmap[i].first != nullptr) 208 | fBitmap[i].second = true; 209 | } 210 | 211 | 212 | BBitmap* 213 | BaseEngine::Page(int pageNumber) 214 | { 215 | if (pageNumber < 0) 216 | pageNumber = 0; 217 | else if (pageNumber >= fPages - 1) 218 | pageNumber = fPages - 1; 219 | 220 | pthread_mutex_lock(&fMutex[pageNumber]); 221 | if (fBitmap[pageNumber].first == nullptr) { 222 | fBitmap[pageNumber] = _RenderBitmap(pageNumber); 223 | } else if (fBitmap[pageNumber].second == true) { 224 | delete fBitmap[pageNumber].first; 225 | fBitmap[pageNumber] = _RenderBitmap(pageNumber); 226 | } 227 | pthread_mutex_unlock(&fMutex[pageNumber]); 228 | fCurrentPageNo = pageNumber; 229 | 230 | return fBitmap[pageNumber].first; 231 | } 232 | 233 | 234 | BRect 235 | BaseEngine::PageMediabox(int pageNumber) 236 | { 237 | BRect rect(0, 0, 1, 1); 238 | 239 | pthread_mutex_lock(&fMutex[pageNumber]); 240 | if (fBitmap[pageNumber].first != nullptr) 241 | rect = fBitmap[pageNumber].first->Bounds(); 242 | 243 | pthread_mutex_unlock(&fMutex[pageNumber]); 244 | 245 | return rect; 246 | } 247 | 248 | 249 | BRect 250 | BaseEngine::PageContentBox(int pageNumber) 251 | { 252 | return PageMediabox(pageNumber); 253 | } 254 | 255 | 256 | BString 257 | BaseEngine::GetPageLabel(int pageNumber) 258 | { 259 | BString label; 260 | label << pageNumber; 261 | 262 | return label; 263 | } 264 | 265 | 266 | BString 267 | BaseEngine::FileName(void) const 268 | { 269 | return BString(""); 270 | } 271 | 272 | 273 | int 274 | BaseEngine::GetPageByLabel(BString label) 275 | { 276 | return atoi(label.String()); 277 | } 278 | 279 | 280 | BString 281 | BaseEngine::GetDecryptionKey(void) const 282 | { 283 | return BString(""); 284 | } 285 | 286 | 287 | void 288 | BaseEngine::SetCacheSize(int forwardCache, int backwardCache) 289 | { 290 | fForwardCache = forwardCache; 291 | fBackwardCache = backwardCache; 292 | } 293 | 294 | 295 | void 296 | BaseEngine::MultiplyZoom(float factor) 297 | { 298 | SetZoom(fZoomFactor * factor); 299 | } 300 | 301 | 302 | void 303 | BaseEngine::WriteOutline(BOutlineListView* list) 304 | { 305 | 306 | } 307 | 308 | void 309 | BaseEngine::StopTextSearch(void) 310 | { 311 | if (fTextSearchThread != nullptr) { 312 | pthread_mutex_lock(&gTextSearchStopMutex); 313 | fStopTextSearchThread = true; 314 | pthread_mutex_unlock(&gTextSearchStopMutex); 315 | void* status; 316 | pthread_join(fTextSearchThread, &status); 317 | fTextSearchThread = nullptr; 318 | } 319 | } 320 | 321 | void 322 | BaseEngine::FindString(BString const& name, BLooper* looper, BHandler* handler, int32 flag) 323 | { 324 | StopTextSearch(); 325 | 326 | if (name.Length() < 2) 327 | return; 328 | 329 | fSearchString = name; 330 | fSearchFlag = flag; 331 | fTargetLooper = looper; 332 | fSearchHandler = handler; 333 | fStopTextSearchThread = false; 334 | pthread_create(&fTextSearchThread, nullptr, _TextSearchThread, (void*)(this)); 335 | } 336 | 337 | 338 | tuple< vector, vector > 339 | BaseEngine::_FindString(BString const& name, int const& page) 340 | { 341 | //empty 342 | return {}; 343 | } 344 | 345 | 346 | void* 347 | BaseEngine::_TextSearchThread(void* arg) 348 | { 349 | rename_thread(find_thread(NULL), "_TextSearchThread"); 350 | 351 | BaseEngine* engine =(BaseEngine*)arg; 352 | int& pages = engine->fPages; 353 | 354 | BString name = engine->fSearchString; 355 | for (int page = 0; page < pages; ++page) { 356 | pthread_mutex_lock(&gTextSearchStopMutex); 357 | if (engine->fStopTextSearchThread) { 358 | engine->fStopTextSearchThread = false; 359 | pthread_mutex_unlock(&gTextSearchStopMutex); 360 | break; 361 | //return nullptr; 362 | } 363 | pthread_mutex_unlock(&gTextSearchStopMutex); 364 | 365 | auto t = engine->_FindString(name, page); 366 | 367 | for (uint32 i = 0; i < get<0>(t).size(); ++i) { 368 | BMessage msg(MSG_SEARCH_RESULT); 369 | msg.AddInt32("page", page); 370 | msg.AddString("context", move(get<0>(t)[i])); 371 | msg.AddRect("rect", move(get<1>(t)[i])); 372 | engine->fTargetLooper->PostMessage(&msg, engine->fSearchHandler); 373 | } 374 | } 375 | 376 | return nullptr; 377 | } 378 | 379 | 380 | bool 381 | BaseEngine::HighlightUnderText(void) 382 | { 383 | return fHighlightUnderText; 384 | } 385 | 386 | -------------------------------------------------------------------------------- /application/BaseEngine.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2012 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #ifndef BASEENGINE_H 10 | #define BASEENGINE_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | #include "Debug.h" 26 | 27 | 28 | class BaseEngine 29 | { 30 | public: 31 | BaseEngine(void); 32 | virtual ~BaseEngine(); 33 | 34 | void Start(void); 35 | void Stop(void); 36 | 37 | void StopTextSearch(void); 38 | 39 | // the name of the file this engine handles 40 | virtual BString FileName(void) const; 41 | // number of pages the loaded document contains 42 | virtual int PageCount(void) const = 0; 43 | 44 | // the box containing the visible page content 45 | // (usually BRect(0, 0, pageWidth, pageHeight)) 46 | virtual BRect PageMediabox(int pageNumber); 47 | // the box inside PageMediabox that actually contains any relevant content 48 | // (used for auto-cropping in Fit Content mode, can be PageMediabox) 49 | virtual BRect PageContentBox(int pageNumber); 50 | 51 | virtual void SetZoom(float zoomFactor); 52 | 53 | // the angle in degrees the given page is rotated natively (usually 0 deg) 54 | virtual int const& PageRotation(int pageNumber); 55 | 56 | virtual std::unique_ptr RenderBitmap(int const& pageNumber,uint32 const& width, 57 | uint32 const& height, int const& rotation = 0) = 0; 58 | 59 | virtual BBitmap* Page(int pageNumber); 60 | 61 | // access to various document properties (such as Author, Title, etc.) 62 | virtual BString GetProperty(BString name) { return BString(""); } 63 | 64 | virtual BString GetPageLabel(int pageNumber); 65 | 66 | // reverts GetPageLabel by returning the first page number 67 | // having the given label 68 | virtual int GetPageByLabel(BString label); 69 | 70 | // returns a string to remember when the user wants to save 71 | // a document's password (don't implement for document types 72 | // that don't support password protection) 73 | virtual BString GetDecryptionKey(void) const; 74 | 75 | virtual void SetCacheSize(int forwardCache, int backwardCache = 0); 76 | virtual void MultiplyZoom(float factor); 77 | 78 | virtual void WriteOutline(BOutlineListView* list); 79 | 80 | virtual void FindString(BString const& name, BLooper* looper, BHandler* handler, 81 | int32 flag = 0); 82 | 83 | bool HighlightUnderText(void); 84 | 85 | bool fStopThread; 86 | 87 | protected: 88 | virtual std::pair _RenderBitmap(int const& pageNumber) = 0; 89 | virtual std::tuple< std::vector, std::vector > 90 | _FindString(BString const& name, int const& page); 91 | 92 | 93 | static void* _DrawingThread(void* arg); 94 | 95 | pthread_t fDrawingThread; 96 | 97 | static pthread_mutex_t gEngineStopMutex; 98 | 99 | 100 | float fZoomFactor; 101 | int fPages; 102 | int fRotation; 103 | int fForwardCache; 104 | int fBackwardCache; 105 | int fCurrentPageNo; 106 | 107 | int32 fSearchFlag; 108 | 109 | std::vector > fBitmap; 110 | std::vector fMutex; 111 | 112 | BRect fDefaultRect; 113 | bool fHighlightUnderText; 114 | 115 | Debug out; 116 | 117 | private: 118 | static void* _TextSearchThread(void* arg); 119 | 120 | pthread_t fTextSearchThread; 121 | 122 | bool fStopTextSearchThread; 123 | 124 | static pthread_mutex_t gTextSearchStopMutex; 125 | 126 | BLooper* fTargetLooper; 127 | BHandler* fSearchHandler; 128 | 129 | BString fSearchString; 130 | }; 131 | 132 | #endif 133 | -------------------------------------------------------------------------------- /application/BookmarksView.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2011 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #include "BookmarksView.h" 10 | 11 | #include 12 | 13 | #include "ImageButton.h" 14 | #include "Messages.h" 15 | 16 | 17 | BookmarkItem::BookmarkItem(const char* name) 18 | : 19 | BListItem(), 20 | fName(name) 21 | { 22 | } 23 | 24 | 25 | BookmarkItem::~BookmarkItem() 26 | { 27 | } 28 | 29 | 30 | void 31 | BookmarkItem::DrawItem(BView *owner, BRect itemRect, bool complete) 32 | { 33 | rgb_color kBlack = {0, 0, 0, 0}; 34 | rgb_color kHighlight = {156, 154, 156, 0}; 35 | 36 | if (IsSelected() || complete) { 37 | rgb_color color; 38 | if (IsSelected()) 39 | color = kHighlight; 40 | else 41 | color = owner->ViewColor(); 42 | 43 | owner->SetHighColor(color); 44 | owner->SetLowColor(color); 45 | owner->FillRect(itemRect); 46 | owner->SetHighColor(kBlack); 47 | 48 | } else { 49 | owner->SetLowColor(owner->ViewColor()); 50 | } 51 | 52 | BFont font = be_plain_font; 53 | font_height finfo; 54 | font.GetHeight(&finfo); 55 | 56 | BPoint point = BPoint(itemRect.left + 5, itemRect.bottom - finfo.descent + 1); 57 | 58 | owner->SetHighColor(kBlack); 59 | owner->SetFont(be_plain_font); 60 | owner->MovePenTo(point); 61 | 62 | owner->MovePenTo(point); 63 | owner->DrawString(fName); 64 | } 65 | 66 | 67 | BookmarkListView::BookmarkListView(void) 68 | : 69 | BOutlineListView("bookmark_listview") 70 | { 71 | 72 | } 73 | 74 | 75 | BookmarksView::BookmarksView(void) 76 | : 77 | BGroupView("Bookmarks_view", B_VERTICAL, 0) 78 | { 79 | ImageButton* bookmarkDeleteButton = new ImageButton("quit", 80 | new BMessage(MSG_ZOOM_IN), 0.3, 1, "Delete bookmark"); 81 | bookmarkDeleteButton->SetExplicitMinSize(BSize(20, 20)); 82 | bookmarkDeleteButton->SetExplicitMaxSize(BSize(20, 20)); 83 | 84 | ImageButton* bookmarkAddButton = new ImageButton("plus", 85 | new BMessage(MSG_ZOOM_OUT), 0.3, 1, "Add bookmark"); 86 | bookmarkAddButton->SetExplicitMinSize(BSize(20, 20)); 87 | bookmarkAddButton->SetExplicitMaxSize(BSize(20, 20)); 88 | 89 | ImageButton* bookmarkEditButton = new ImageButton("edit", 90 | new BMessage(MSG_NO_FIT), 0.3, 1, "Edit bookmark"); 91 | bookmarkEditButton->SetExplicitMinSize(BSize(20, 20)); 92 | bookmarkEditButton->SetExplicitMaxSize(BSize(20, 20)); 93 | 94 | BookmarkItem* item1 = new BookmarkItem("Test1"); 95 | // item1->SetOutlineLevel(1); 96 | BookmarkItem* item2 = new BookmarkItem("Test2"); 97 | //item2->SetOutlineLevel(0); 98 | BookmarkItem* item3 = new BookmarkItem("Test3"); 99 | //item2->SetOutlineLevel(0); 100 | BookmarkItem* item4 = new BookmarkItem("Test4"); 101 | BookmarkItem* item5 = new BookmarkItem("Test5"); 102 | 103 | fBookmarkListView = new BookmarkListView(); 104 | fBookmarkListView->AddItem(item1); 105 | fBookmarkListView->AddUnder(item3, item1); 106 | fBookmarkListView->AddUnder(item2, item1); 107 | fBookmarkListView->AddItem(item4); 108 | fBookmarkListView->AddItem(item5); 109 | 110 | fVScrollBar = new BScrollBar("v_scrollbar", 111 | fBookmarkListView, 0, 2000, B_VERTICAL); 112 | fHScrollBar = new BScrollBar("h_scrollbar", 113 | fBookmarkListView, 0, 2000, B_HORIZONTAL); 114 | 115 | fSearchTC = new BTextControl("", "", nullptr); 116 | 117 | BLayoutBuilder::Group<>(this) 118 | .AddGroup(B_HORIZONTAL, 0) 119 | .Add(bookmarkAddButton) 120 | .Add(bookmarkEditButton) 121 | .Add(bookmarkDeleteButton) 122 | .Add(fSearchTC) 123 | //.AddGlue(100) 124 | .End() 125 | .AddGroup(B_HORIZONTAL, 0) 126 | .Add(fBookmarkListView) 127 | .Add(fVScrollBar) 128 | .End() 129 | .Add(fHScrollBar) 130 | .End() 131 | ; 132 | } 133 | -------------------------------------------------------------------------------- /application/BookmarksView.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2011 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #ifndef BOOKMARKSVIEW_H 10 | #define BOOKMARKSVIEW_H 11 | 12 | #include 13 | 14 | extern "C" { 15 | #include 16 | } 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "Debug.h" 26 | 27 | class BookmarkItem : public BListItem 28 | { 29 | public: 30 | BookmarkItem(const char* name); 31 | ~BookmarkItem(); 32 | virtual void DrawItem(BView* owner, BRect itemRect, bool = false); 33 | private: 34 | BString fName; 35 | }; 36 | 37 | 38 | class BookmarkListView : public BOutlineListView 39 | { 40 | public: 41 | BookmarkListView(void); 42 | 43 | private: 44 | 45 | }; 46 | 47 | 48 | class BookmarksView : public BGroupView 49 | { 50 | public: 51 | BookmarksView(void); 52 | 53 | private: 54 | BScrollBar* fVScrollBar; 55 | BScrollBar* fHScrollBar; 56 | 57 | BTextControl* fSearchTC; 58 | BookmarkListView* fBookmarkListView; 59 | }; 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /application/CircleMenuView.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2011 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | 10 | #include "CircleMenuView.h" 11 | 12 | #include 13 | #include 14 | 15 | using namespace std; 16 | 17 | CircleMenuView::CircleMenuView(BRect const& frame, int width, BString const& name) 18 | : 19 | BView(frame, name, B_FOLLOW_LEFT | B_FOLLOW_TOP, 20 | B_FULL_UPDATE_ON_RESIZE | B_WILL_DRAW | B_DRAW_ON_CHILDREN) 21 | { 22 | SetEventMask(EventMask() | B_FULL_POINTER_HISTORY); 23 | SetDrawingMode(B_OP_ALPHA); 24 | SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); 25 | SetPenSize(3); 26 | 27 | fBgColor = make_color(180, 180, 255, 180); 28 | SetViewColor(fBgColor); 29 | fMarginColor = tint_color(fBgColor, B_DARKEN_4_TINT); 30 | /* 31 | m_nWidth = nWidth; 32 | m_cBounds = cFrame.Bounds(); 33 | 34 | int nROut = static_cast< int >( m_cBounds.Width() / 2 ); 35 | int nRIn = nROut - m_nWidth ; 36 | 37 | m_cCenter = IPoint( nROut, nROut ); 38 | 39 | m_vRMiddle = nRIn + m_nWidth / 2; 40 | 41 | m_pcImage = DrawRing( nROut, nRIn, 0.0, 0.0, 0.0, 0.6 ); 42 | 43 | Hide(); 44 | */ 45 | fCenterPoint = BPoint(frame.Width() / 2, frame.Height() / 2); 46 | fROut = std::min(frame.Width() / 2, frame.Height() / 2); 47 | fROut -= 10; 48 | fRIn = fROut- width; 49 | fRMiddle = (fROut + fRIn) / 2; 50 | if (IsHidden() == false) 51 | Hide(); 52 | } 53 | 54 | 55 | void 56 | CircleMenuView::Draw(BRect updateRect) 57 | { 58 | SetHighColor(fBgColor); 59 | BPoint center(Bounds().Width()/2, Bounds().Height()/2); 60 | // FillEllipse(center, center.x, center.x - 10); 61 | FillArc(fCenterPoint, fROut, fROut, 0, 360); 62 | SetHighColor(B_TRANSPARENT_32_BIT); 63 | FillArc(fCenterPoint, fRIn, fRIn, 0, 360); 64 | SetHighColor(fMarginColor); 65 | StrokeArc(fCenterPoint, fROut, fROut, 0, 360); 66 | StrokeArc(fCenterPoint, fRIn, fRIn, 0, 360); 67 | } 68 | 69 | 70 | void 71 | CircleMenuView::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage) 72 | { 73 | BView::MouseMoved(where, code, dragMessage); 74 | if((pow((where.x - fCenterPoint.x),2) + 75 | pow((where.y - fCenterPoint.y),2)) >= pow(fROut,2)) { 76 | if (IsHidden() == false) 77 | Hide(); 78 | 79 | Parent()->MakeFocus(true); 80 | } 81 | } 82 | 83 | 84 | void 85 | CircleMenuView::AddChild(BView* view) 86 | { 87 | BView::AddChild(view); 88 | AlignViews(); 89 | } 90 | 91 | 92 | void 93 | CircleMenuView::RemoveChild(BView* view) 94 | { 95 | 96 | 97 | } 98 | 99 | 100 | void 101 | CircleMenuView::AlignViews(void) 102 | { 103 | if (Parent() == NULL) 104 | return; 105 | 106 | float children = CountChildren(); 107 | float numberOfChild = 0; 108 | BView* child = ChildAt(0); 109 | 110 | while (child != NULL) { 111 | complex pos(polar(fRMiddle, static_cast< float >(M_PI/2) + 112 | numberOfChild*2* static_cast< float >(M_PI) / children)); 113 | 114 | float width = child->Bounds().Width(); 115 | float height = child->Bounds().Height(); 116 | 117 | //rect.right = fCenterPoint.x + pos.real() + width/2; 118 | //rect.bottom = fCenterPoint.y - pos.imag() + height/2; 119 | 120 | child->MoveTo(fCenterPoint.x + pos.real() - width/2, 121 | fCenterPoint.y - pos.imag() - height/2); 122 | child->ResizeTo(49, 49); 123 | child->ResizeBy(1, 1); 124 | child->Invalidate(); 125 | //child->Show(); 126 | ++numberOfChild; 127 | child = child->NextSibling(); 128 | } 129 | 130 | Invalidate(); 131 | } 132 | 133 | 134 | void 135 | CircleMenuView::AttachedToWindow(void) 136 | { 137 | BView::AttachedToWindow(); 138 | 139 | AlignViews(); 140 | Invalidate(); 141 | } 142 | -------------------------------------------------------------------------------- /application/CircleMenuView.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2011 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | 10 | #ifndef CIRCLEMENUVIEW 11 | #define CIRCLEMENUVIEW 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "Debug.h" 21 | 22 | class CircleMenuView : public BView 23 | { 24 | public: 25 | CircleMenuView(BRect const& frame, int width = 60, 26 | BString const& name = "circle_menu"); 27 | 28 | virtual void Draw(BRect updateRect); 29 | virtual void MouseMoved(BPoint where, uint32 code, 30 | const BMessage* dragMessage); 31 | virtual void AddChild(BView* view); 32 | virtual void RemoveChild(BView* view); 33 | virtual void AlignViews(void); 34 | virtual void AttachedToWindow(void); 35 | 36 | private: 37 | std::list fViewList; 38 | float fROut; 39 | float fRIn; 40 | float fRMiddle; 41 | BPoint fCenterPoint; 42 | 43 | rgb_color fBgColor; 44 | rgb_color fMarginColor; 45 | 46 | BGradientLinear fTransparentGradient; 47 | Debug out; 48 | }; 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /application/DJVUEngine.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2012 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #include "DJVUEngine.h" 10 | 11 | #include 12 | #include 13 | 14 | #include "Flags.h" 15 | #include "Messages.h" 16 | #include "OutlineView.h" 17 | #include "PasswordRequestWindow.h" 18 | 19 | using namespace std; 20 | 21 | pthread_mutex_t DJVUEngine::gRendermutex; 22 | 23 | DJVUEngine::DJVUEngine(BString fileName, BString& password) 24 | : 25 | fFileName(fileName), 26 | fPassword(password) 27 | { 28 | 29 | fContext = ddjvu_context_create("DJVUEngine"); 30 | ddjvu_cache_set_size(fContext, 30E6); 31 | fDocument = ddjvu_document_create_by_filename_utf8(fContext, 32 | fileName.String(), TRUE); 33 | 34 | while (!ddjvu_document_decoding_done(fDocument)) 35 | _HandleDjvuMessages(fContext, true); 36 | 37 | if (ddjvu_document_decoding_error(fDocument)) 38 | throw; 39 | 40 | Start(); 41 | } 42 | 43 | 44 | DJVUEngine::~DJVUEngine() 45 | { 46 | Stop(); 47 | 48 | ddjvu_document_release(fDocument); 49 | ddjvu_context_release(fContext); 50 | 51 | minilisp_finish(); 52 | } 53 | 54 | 55 | void 56 | DJVUEngine::_HandleDjvuMessages(ddjvu_context_t *context, int wait) 57 | { 58 | if (wait) 59 | ddjvu_message_wait(context); 60 | 61 | const ddjvu_message_t *msg; 62 | while ((msg = ddjvu_message_peek(context))) { 63 | switch(msg->m_any.tag) { 64 | case DDJVU_ERROR: 65 | !out << "djvu-error: " << msg->m_error.message << endl; 66 | break; 67 | 68 | default: 69 | break; 70 | } 71 | ddjvu_message_pop(context); 72 | } 73 | } 74 | 75 | 76 | int 77 | DJVUEngine::PageCount(void) const 78 | { 79 | return ddjvu_document_get_pagenum(fDocument); 80 | } 81 | 82 | 83 | void 84 | DJVUEngine::WriteOutline(BOutlineListView* list) 85 | { 86 | std::function OutlineToList = 87 | [&OutlineToList](miniexp_t outline, BOutlineListView* list, BListItem* super, int level) { 88 | for (miniexp_t rest = outline; miniexp_consp(rest); rest = miniexp_cdr(rest)) { 89 | miniexp_t item = miniexp_car(rest); 90 | if (!miniexp_consp(item) || !miniexp_consp(miniexp_cdr(item)) || 91 | !miniexp_stringp(miniexp_car(item)) || !miniexp_stringp(miniexp_cadr(item))) 92 | continue; 93 | 94 | BString link(miniexp_to_str(miniexp_cadr(item))); 95 | BString name(miniexp_to_str(miniexp_car(item))); 96 | 97 | link.RemoveAll("#"); 98 | int pageNumber= atoi(link.String()) - 1; 99 | OutlineItem* listItem = new OutlineItem(name, pageNumber); 100 | list->AddUnder(listItem, super); 101 | OutlineToList(miniexp_cddr(item),list, listItem, level + 1); 102 | } 103 | }; 104 | 105 | miniexp_t outline; 106 | 107 | while ((outline = ddjvu_document_get_outline(fDocument)) == miniexp_dummy) 108 | _HandleDjvuMessages(fContext); 109 | 110 | if (!miniexp_consp(outline) || miniexp_car(outline) != miniexp_symbol("bookmarks")) { 111 | ddjvu_miniexp_release(fDocument, outline); 112 | return; 113 | } 114 | 115 | OutlineToList(outline, list, nullptr, 0); 116 | 117 | 118 | ddjvu_miniexp_release(fDocument, outline); 119 | } 120 | 121 | 122 | BString 123 | DJVUEngine::GetProperty(BString name) 124 | { 125 | BString property; 126 | 127 | return property; 128 | } 129 | 130 | 131 | BString 132 | DJVUEngine::FileName(void) const 133 | { 134 | return fFileName; 135 | } 136 | 137 | 138 | 139 | 140 | unique_ptr 141 | DJVUEngine::RenderBitmap(int const& pageNumber, 142 | uint32 const& width, uint32 const& height, int const& rotation) 143 | { 144 | if (pageNumber < 0 || pageNumber >= fPages) { 145 | return unique_ptr(nullptr); 146 | } 147 | 148 | ddjvu_page_t *page = ddjvu_page_create_by_pageno(fDocument, pageNumber); 149 | if (!page) 150 | return unique_ptr(nullptr); 151 | 152 | while (!ddjvu_page_decoding_done(page)) 153 | _HandleDjvuMessages(fContext); 154 | 155 | if (ddjvu_page_decoding_error(page)) 156 | return unique_ptr(nullptr); 157 | 158 | 159 | ddjvu_rect_t prect = {0,0, width, height}; 160 | 161 | if (prect.w <= 0) { 162 | if (prect.h <= 0) 163 | throw "DJVUEngine::RenderBitmap - illegal size"; 164 | 165 | prect.w = prect.h * ddjvu_page_get_width(page) / ddjvu_page_get_height(page); 166 | } else if (prect.h <= 0) { 167 | prect.h = prect.w * ddjvu_page_get_height(page) / ddjvu_page_get_width(page); 168 | } 169 | 170 | 171 | ddjvu_rect_t rrect = prect; 172 | 173 | BBitmap* bitmap; 174 | ddjvu_render_mode_t mode; 175 | ddjvu_format_t *fmt; 176 | 177 | if (DDJVU_PAGETYPE_BITONAL == ddjvu_page_get_type(page)) { 178 | bitmap = new BBitmap(BRect(0, 0, prect.w - 1, prect.h - 1), B_GRAY8); 179 | fmt = ddjvu_format_create(DDJVU_FORMAT_GREY8, 0, NULL); 180 | mode = DDJVU_RENDER_MASKONLY; 181 | } else { 182 | bitmap = new BBitmap(BRect(0, 0, prect.w - 1, prect.h - 1), B_RGB24); 183 | fmt = ddjvu_format_create(DDJVU_FORMAT_BGR24, 0, NULL); 184 | mode = DDJVU_RENDER_COLOR; 185 | } 186 | 187 | ddjvu_format_set_row_order(fmt, TRUE); 188 | 189 | if (!ddjvu_page_render(page, mode, &prect, &rrect, fmt, bitmap->BytesPerRow(), 190 | (char*)bitmap->Bits())) 191 | return unique_ptr(nullptr); 192 | 193 | ddjvu_format_release(fmt); 194 | ddjvu_page_release(page); 195 | 196 | return unique_ptr(bitmap); 197 | } 198 | 199 | 200 | std::pair 201 | DJVUEngine::_RenderBitmap(int const& pageNumber) 202 | { 203 | pthread_mutex_lock(&gRendermutex); 204 | 205 | ddjvu_page_t *page = ddjvu_page_create_by_pageno(fDocument, pageNumber); 206 | if (!page) { 207 | pthread_mutex_unlock(&gRendermutex); 208 | return std::pair(new BBitmap(fDefaultRect, B_RGBA32), false); 209 | } 210 | 211 | while (!ddjvu_page_decoding_done(page)) 212 | _HandleDjvuMessages(fContext); 213 | 214 | if (ddjvu_page_decoding_error(page)) { 215 | pthread_mutex_unlock(&gRendermutex); 216 | return std::pair(new BBitmap(fDefaultRect, B_RGBA32), false); 217 | } 218 | 219 | ddjvu_rect_t prect = {0, 0, 0, 0}; 220 | prect.w = ddjvu_page_get_width(page) * fZoomFactor * 0.1; 221 | prect.h = ddjvu_page_get_height(page) * fZoomFactor * 0.1; 222 | ddjvu_rect_t rrect = prect; 223 | 224 | BBitmap* bitmap; 225 | ddjvu_render_mode_t mode; 226 | ddjvu_format_t *fmt; 227 | 228 | if (DDJVU_PAGETYPE_BITONAL == ddjvu_page_get_type(page)) { 229 | bitmap = new BBitmap(BRect(0, 0, prect.w - 1, prect.h - 1), B_GRAY8); 230 | fmt = ddjvu_format_create(DDJVU_FORMAT_GREY8, 0, NULL); 231 | mode = DDJVU_RENDER_MASKONLY; 232 | } else { 233 | bitmap = new BBitmap(BRect(0, 0, prect.w - 1, prect.h - 1), B_RGB24); 234 | fmt = ddjvu_format_create(DDJVU_FORMAT_BGR24, 0, NULL); 235 | mode = DDJVU_RENDER_COLOR; 236 | } 237 | 238 | ddjvu_format_set_row_order(fmt, /* top_to_bottom */ TRUE); 239 | 240 | if (!ddjvu_page_render(page, mode, &prect, &rrect, fmt, bitmap->BytesPerRow(), 241 | (char*)bitmap->Bits())) { 242 | pthread_mutex_unlock(&gRendermutex); 243 | return std::pair(new BBitmap(fDefaultRect, B_RGBA32), false); 244 | } 245 | ddjvu_format_release(fmt); 246 | ddjvu_page_release(page); 247 | pthread_mutex_unlock(&gRendermutex); 248 | 249 | return std::pair(bitmap, false); 250 | } 251 | 252 | 253 | tuple< vector, vector > 254 | DJVUEngine::_FindString(BString const& name, int const& page) 255 | { 256 | vector contextVec; 257 | vector rectVec; 258 | 259 | vector textVec; 260 | 261 | bool needWholeWord = false; 262 | if (GHasFlag(fSearchFlag, SEARCH_WHOLE_WORD)) 263 | needWholeWord = true; 264 | 265 | bool needMatchCase = false; 266 | if (GHasFlag(fSearchFlag, SEARCH_MATCH_CASE)) 267 | needMatchCase = true; 268 | 269 | float pageWidth = 1; 270 | float pageHeight = 1; 271 | 272 | function _SearchInExpression = 273 | [&](miniexp_t expression) { 274 | miniexp_t type = miniexp_car(expression); 275 | if (!miniexp_symbolp(type)) 276 | return; 277 | 278 | expression = miniexp_cdr(expression); 279 | BRect rect; 280 | 281 | rect.left = miniexp_to_int(miniexp_car(expression)); 282 | expression = miniexp_cdr(expression); 283 | rect.bottom = miniexp_to_int(miniexp_car(expression)); 284 | expression = miniexp_cdr(expression); 285 | rect.right = miniexp_to_int(miniexp_car(expression)); 286 | expression = miniexp_cdr(expression); 287 | rect.top = miniexp_to_int(miniexp_car(expression)); 288 | expression = miniexp_cdr(expression); 289 | Debug out; 290 | miniexp_t str = miniexp_car(expression); 291 | 292 | if (miniexp_symbol("page") == type) { 293 | pageWidth = rect.Width(); 294 | pageHeight = -rect.Height(); 295 | } 296 | 297 | 298 | if (miniexp_stringp(str) && !miniexp_cdr(expression)) { 299 | BString tempStr = miniexp_to_str(str); 300 | bool foundMatch = false; 301 | if (needMatchCase) { 302 | if (tempStr.FindFirst(name) != B_ERROR) { 303 | if (needWholeWord) { 304 | if (tempStr.Length() == name.Length()) 305 | foundMatch = true; 306 | } else { 307 | foundMatch = true; 308 | } 309 | } 310 | } else { 311 | if (tempStr.IFindFirst(name) != B_ERROR) { 312 | if (needWholeWord) { 313 | if (tempStr.Length() == name.Length()) 314 | foundMatch = true; 315 | } else { 316 | foundMatch = true; 317 | } 318 | } 319 | } 320 | 321 | if (foundMatch) { 322 | rect.left = rect.left / pageWidth; 323 | rect.right = rect.right/ pageWidth; 324 | rect.top = (pageHeight - rect.top) / pageHeight; 325 | rect.bottom = (pageHeight - rect.bottom) / pageHeight; 326 | rectVec.push_back(rect); 327 | } 328 | 329 | textVec.push_back(move(tempStr)); 330 | expression = miniexp_cdr(expression); 331 | } 332 | 333 | while (miniexp_consp(str)) { 334 | _SearchInExpression(str); 335 | expression = miniexp_cdr(expression); 336 | str = miniexp_car(expression); 337 | } 338 | 339 | return; 340 | }; 341 | 342 | auto _SearchInPage = [&](int page) { 343 | miniexp_t pagetext; 344 | while ((pagetext = ddjvu_document_get_pagetext(fDocument, page, "word")) == miniexp_dummy) 345 | _HandleDjvuMessages(fContext, true); 346 | 347 | if (miniexp_nil == pagetext) 348 | return; 349 | 350 | _SearchInExpression(pagetext); 351 | 352 | ddjvu_miniexp_release(fDocument, pagetext); 353 | }; 354 | 355 | _SearchInPage(page); 356 | 357 | int deltaIndexLeft = 4; 358 | int deltaIndexRight = 4; 359 | 360 | bool foundMatch = false; 361 | 362 | for (uint32 i = 0; i < textVec.size(); ++i) { 363 | foundMatch = false; 364 | 365 | if (needMatchCase) { 366 | if (textVec[i].FindFirst(name) != B_ERROR) { 367 | if (needWholeWord) { 368 | if (textVec[i].Length() == name.Length()) 369 | foundMatch = true; 370 | } else { 371 | foundMatch = true; 372 | } 373 | } 374 | } else { 375 | if (textVec[i].IFindFirst(name) != B_ERROR) { 376 | if (needWholeWord) { 377 | if (textVec[i].Length() == name.Length()) 378 | foundMatch = true; 379 | } else { 380 | foundMatch = true; 381 | } 382 | } 383 | } 384 | 385 | if (foundMatch == true) { 386 | int from = i - deltaIndexLeft; 387 | if (from < 0) 388 | from = 0; 389 | 390 | uint32 to = i + deltaIndexRight; 391 | if (to >= textVec.size()) 392 | to = textVec.size() - 1; 393 | 394 | BString str; 395 | for (uint32 j = from; j < to; ++j) { 396 | str += textVec[j]; 397 | str += " "; 398 | } 399 | 400 | str += textVec[to]; 401 | 402 | contextVec.push_back(str); 403 | } 404 | } 405 | 406 | return make_tuple(contextVec, rectVec); 407 | } 408 | -------------------------------------------------------------------------------- /application/DJVUEngine.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2012 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #ifndef DJVUENGINE_H 10 | #define DJVUENGINE_H 11 | 12 | #include 13 | 14 | #include 15 | 16 | #include 17 | #include 18 | 19 | #include "BaseEngine.h" 20 | #include "Debug.h" 21 | 22 | class DJVUEngine : public BaseEngine 23 | { 24 | public: 25 | DJVUEngine(BString filename, BString& password); 26 | 27 | virtual ~DJVUEngine(); 28 | 29 | virtual BString FileName(void) const; 30 | int PageCount(void) const; 31 | 32 | virtual BString GetProperty(BString name); 33 | 34 | virtual void WriteOutline(BOutlineListView* list); 35 | 36 | virtual std::unique_ptr RenderBitmap(int const& pageNumber,uint32 const& width, 37 | uint32 const& height, int const& rotation = 0); 38 | 39 | private: 40 | virtual std::pair _RenderBitmap(int const& pageNumber); 41 | 42 | virtual std::tuple< std::vector, std::vector > 43 | _FindString(BString const& name, int const& page); 44 | 45 | void _HandleDjvuMessages(ddjvu_context_t *context, 46 | int wait = false); 47 | 48 | BString fFileName; 49 | BString fPassword; 50 | 51 | ddjvu_context_t* fContext; 52 | ddjvu_document_t* fDocument; 53 | 54 | static pthread_mutex_t gRendermutex; 55 | 56 | Debug out; 57 | }; 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /application/Debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2011 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #ifndef DEBUG_H 10 | #define DEBUG_H 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | using std::endl; 17 | 18 | #if DEBUG == 1 19 | 20 | class Debug 21 | { 22 | public: 23 | Debug(void) 24 | : 25 | fStr(""), 26 | fState(true) 27 | { 28 | 29 | } 30 | 31 | Debug(BString str) 32 | : 33 | fStr(""), 34 | fState(true) 35 | { 36 | std::cout << str.String() << std::endl; 37 | } 38 | 39 | 40 | Debug& operator<<(std::ostream& (*f)(std::ostream&)) 41 | { 42 | std::cout< 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include "BaseEngine.h" 20 | #include "CircleMenuView.h" 21 | #include "Debug.h" 22 | #include "ImageButton.h" 23 | 24 | 25 | class BasicDocumentView : public BView 26 | { 27 | public: 28 | BasicDocumentView(BString filename, BString fileType, 29 | BString& password); 30 | ~BasicDocumentView(); 31 | 32 | virtual void Draw(BRect updateRect); 33 | virtual void FrameResized(float newWidth, float newHeight); 34 | virtual void KeyDown(const char* bytes, int32 numBytes); 35 | virtual void MessageReceived(BMessage* message); 36 | virtual void MouseDown(BPoint where); 37 | virtual void MouseUp(BPoint where); 38 | virtual void MouseMoved(BPoint where, uint32 code, 39 | const BMessage* dragMessage); 40 | virtual void ScrollTo(BPoint where); 41 | virtual void AllAttached(void); 42 | virtual void Pulse(); 43 | 44 | void SetFile(const BString& file, BString const& fileType, 45 | BString& password); 46 | 47 | friend class DocumentView; 48 | 49 | enum { 50 | M_INIT = 'ii01' 51 | }; 52 | 53 | private: 54 | void _GoToPage(int32 pageNumber); 55 | void _NotifyPageChange(const int& pageNumber); 56 | void _SetScrollBarAtPage(int pageNumber); 57 | void _ShowPage(const int& pagenumber); 58 | void _ShowCurrentPage(void); 59 | void _AdaptScrollBarRange(void); 60 | void _AdaptCache(void); 61 | void _FitPageHeight(void); 62 | void _FitPageWidth(void); 63 | void _ScrollDownBigStep(void); 64 | void _ScrollDownSmallStep(void); 65 | void _ScrollUpBigStep(void); 66 | void _ScrollUpSmallStep(void); 67 | 68 | // BRect _PageFrame(const int& pageNumber); 69 | BRect _PageFrame(BBitmap* bitmap, const int& pageNumber); 70 | 71 | std::unique_ptr fEngine; 72 | CircleMenuView* fCircleMenu; 73 | 74 | 75 | BPoint fOldMousePos; 76 | uint32 fMouseButtons; 77 | uint32 fCurrentFit; 78 | 79 | float fZoomFactor; 80 | float fZoomStep; 81 | float fSmallScrollStep; 82 | 83 | int fCurrentPageNumber; 84 | bool fIsPanning; 85 | bool fIsHPanning; 86 | bool fIsVPanning; 87 | bool fNeedsResize; 88 | bool fIsPrinting; 89 | bool fHighlightUnderText; 90 | 91 | std::tuple fHighlightRect; 92 | 93 | Debug out; 94 | }; 95 | 96 | 97 | class DocumentView : public BGroupView 98 | { 99 | public: 100 | DocumentView(BString filename, BString fileType, BString& password); 101 | virtual void MessageReceived(BMessage* message); 102 | virtual void FileChanged(const BString& file, BString const& fileType, 103 | BString& password); 104 | 105 | void Print(void); 106 | int PageCount(void); 107 | 108 | BBitmap* ImagePage(int const& pageNumber, float const& height = 500); 109 | 110 | 111 | 112 | std::unique_ptr 113 | Cover(float const& height = 500); 114 | 115 | virtual void MakeFocus(bool focus); 116 | 117 | const int& CurrentPageNumber(void); 118 | 119 | private: 120 | BasicDocumentView* fBasicDocumentView; 121 | BScrollBar* fVScrollBar; 122 | BScrollBar* fHScrollBar; 123 | 124 | Debug out; 125 | }; 126 | 127 | #endif 128 | -------------------------------------------------------------------------------- /application/DocumentViewer.rdef: -------------------------------------------------------------------------------- 1 | resource app_flags B_MULTIPLE_LAUNCH; 2 | 3 | resource app_version { 4 | major = 0, 5 | middle = 3, 6 | minor = 0, 7 | 8 | variety = B_APPV_ALPHA, 9 | internal = 1, 10 | 11 | short_info = "DocumentViewer", 12 | long_info = "DocumentViewer based on MuPDF DjVuLibre libCHM ebook-tools" 13 | }; 14 | 15 | resource app_signature "application/x-vnd.documentviewer"; 16 | 17 | resource file_types message { 18 | "types" = "application/x-pdf", 19 | "types" = "application/pdf", 20 | "types" = "application/x-djvu", 21 | "types" = "application/vnd.ms-xpsdocument" 22 | }; 23 | 24 | resource vector_icon { 25 | $"6E6369661F03010000020016023CC7EE389BC0BA16573E39B04977C842ADC700" 26 | $"FFFFD3020016023C529D3753A2B8966F3D9D074B6044496AAF0047FFA0020016" 27 | $"02BC4E76BC411B3C90DABCA00D47587D4ABA850090FFD40200160238313C3B5C" 28 | $"F0BFCD963C7AAC4C13943FCAF901ECFFC3054B04016B020006033E2F99387F17" 29 | $"BA42DB3FF5B94A0E32482C90001D1E2C3D454658FF010101020006023879063B" 30 | $"8224BE2CC83B10DB4A1F6F49B89400242222FF9A9A9A020006033C69A6000000" 31 | $"0000003E186148800049800000D4CECE58F3F3F3FFD9D9D9038DFF0603FF0000" 32 | $"05FF05010200160338D2F73CD163BF82B23B84A94B88504870C900D6BDF5FFE6" 33 | $"020116023E49240000000000003CAAAA4940004A3000FFEA7CA3040192020016" 34 | $"023A55A6BAC2293F0DA33E958646C2EB47A1D60001FF9E035C020203FF050505" 35 | $"0104005305000200160338D2F73CD163BF82B23B84A94B88504870C900E7BDFF" 36 | $"FFEB0501020106023E49240000000000003CAAAA4940004A30007CFFC0C0FFF4" 37 | $"F4F4040192020016023A55A6BAC2293F0DA33E958646C2EB47A1D60001FF9E05" 38 | $"FF020006023B61A038E755B9F2003C4C154AC9623D6A0500FF6D6DFFDA1C1C02" 39 | $"00060239658D3E8928BDB2D1387A224A2B6346C66B6B06F8B7FF1467FF270000" 40 | $"00000A062228224A485E525252302C220A042228483852302C220A044838485E" 41 | $"525252300A042228224A485E48380A04453A45572446242C0A04B560C1592446" 42 | $"242CB569B8200A0445544557244626440A04453A45542644B569B8200A043826" 43 | $"3D234E28492C080438263D234E284E2E0A03492C4E284E2E0802425843C9830A" 44 | $"06486054606052CA1BC5B95C4D524800000206403B383A483C4E38523C4C3643" 45 | $"3E473A3E433E4B3A4B434B3B3D3E42BCBBBCD833353534B87EBC670A04B77BBB" 46 | $"B7B7E137B77BBC9CB722370A04B77BBBB7B7E137B77BBC9CB7223702044030C3" 47 | $"4530BC3A30304030BC3A30C3454050BC3A50C34550504050C34550BC3A000002" 48 | $"044030C34530BC3A30304030BC3A30C3454050BC3A50C34550504050C34550BC" 49 | $"3A0A04B722B9F9B609BB11B722BC43B854BB1E0606AE0BB40BBF4D33C3AEB75C" 50 | $"C172BDEFC606C13EC804CA27BD82C117B920C51BBB40BF06B8073AB6BC0605AE" 51 | $"02B57D3EB9B9C3EFB7BB44BBB751BD75C936CA8DC1B0402F0A093B593D5BBFCD" 52 | $"C93D455BC516C5F060465B435D4544510A045A425E3F5A3D5740080238333D2E" 53 | $"08023D36413208024139463408023A484A3708023E4B4E390802424E4F3F0606" 54 | $"F60F3E3022492444244D245A2255225A225A305A30553049324D3244320404B6" 55 | $"412E2745294526452C422B0604F649272E4E2C4E2F4E2C4E294EB71B4E260803" 56 | $"522E522756270802522B552B0A04283E3E4C50383A2E100A06010E000A00010B" 57 | $"1001178400040A04010A000A05010C000A0001021001178400040A010103000A" 58 | $"020104000A03020506000A070109000A080107000A090108000A0A010D1815FF" 59 | $"01178220040A0C020F09000A180121123F79990000000000003F7999C8240048" 60 | $"F40001178402040A1D0121023F79990000000000003F7999C8240048F4000A1C" 61 | $"04242223251A3F79990000000000003F7999C8240048F40015FF0117822204" 62 | }; 63 | -------------------------------------------------------------------------------- /application/DocumentViewer_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HaikuArchives/DocumentViewer/963d1176cdfe9aab945531633f01334eaac0a686/application/DocumentViewer_icon.png -------------------------------------------------------------------------------- /application/Flags.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2012 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #ifndef FLAGS_H 10 | #define FLAGS_H 11 | 12 | inline bool GHasFlag(int const& kValue, int const& kFlag) 13 | { 14 | return ((kValue & kFlag) == kFlag); 15 | } 16 | 17 | const int SEARCH_MATCH_CASE = 1 << 0 ; 18 | const int SEARCH_WHOLE_WORD = 1 << 1 ; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /application/ImageButton.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2011 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #include "ImageButton.h" 10 | 11 | #include 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "Tools.h" 21 | 22 | using namespace std; 23 | 24 | ImageButton::ImageButton(BString imageName,BMessage *message, 25 | float marginProportion, int frameBehaviour, 26 | const char* tooltip, const char* name, uint32 flags) 27 | : 28 | BButton(name, "", message, flags), 29 | fImageName(imageName), 30 | fBitmap(nullptr), 31 | fMarginProportion(1 - marginProportion), 32 | fFrameBehaviour(frameBehaviour), 33 | fMouseState(MOUSE_OUTSIDE), 34 | fShowFrame(false), 35 | fLongPush(false), 36 | fLongPushLimit(500) 37 | { 38 | SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED)); 39 | SetExplicitPreferredSize(BSize(50, 30)); 40 | 41 | //SetViewColor(B_TRANSPARENT_32_BIT); 42 | SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 43 | SetDrawingMode(B_OP_ALPHA); 44 | SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); 45 | /* 46 | BScreen screen; 47 | 48 | monitor_info info; 49 | screen.GetMonitorInfo(&info); 50 | 51 | !out << "Width: " << info.width << " Height " << info.height << std::endl; 52 | */ 53 | 54 | fTimer = unique_ptr(new Timer); 55 | 56 | fGradientHighlight.SetStart(0, 0); 57 | fGradientPressed.SetStart(0, 0); 58 | 59 | if (tooltip != NULL) 60 | SetToolTip(tooltip); 61 | } 62 | 63 | 64 | void 65 | ImageButton::Draw(BRect updateRect) 66 | { 67 | switch (fFrameBehaviour) { 68 | case 0: case 1: 69 | break; 70 | 71 | case 2: 72 | 73 | 74 | break; 75 | 76 | default: 77 | break; 78 | } 79 | 80 | 81 | switch (fFrameBehaviour) { 82 | case 0: 83 | BButton::Draw(updateRect); 84 | break; 85 | 86 | case 1: 87 | if (fMouseState == MOUSE_OUTSIDE) { 88 | SetHighColor(Parent()->ViewColor()); 89 | FillRect(Bounds()); 90 | } else { 91 | BButton::Draw(updateRect); 92 | } 93 | break; 94 | 95 | case 2: 96 | switch (fMouseState) { 97 | case MOUSE_OUTSIDE: 98 | if (Parent()->ViewColor().alpha == 255) { 99 | SetHighColor(Parent()->ViewColor()); 100 | FillRect(Bounds()); 101 | } 102 | break; 103 | 104 | case MOUSE_INSIDE: 105 | FillEllipse(Bounds(), fGradientHighlight); 106 | break; 107 | 108 | case MOUSE_PRESSED: 109 | FillEllipse(Bounds(), fGradientPressed); 110 | SetHighColor(fMarginColor); 111 | StrokeEllipse(Bounds()); 112 | break; 113 | 114 | default: 115 | break; 116 | } 117 | break; 118 | 119 | default: 120 | break; 121 | } 122 | 123 | if (fBitmap == nullptr) 124 | fBitmap = Tools::LoadBitmap(fImageName, fImageRect.Width()); 125 | 126 | DrawBitmapAsync(fBitmap, fImageRect.LeftTop() + fOffset); 127 | 128 | Sync(); 129 | } 130 | 131 | 132 | void 133 | ImageButton::AttachedToWindow(void) 134 | { 135 | BButton::AttachedToWindow(); 136 | if (Parent() != nullptr) 137 | fBgColor = Parent()->ViewColor(); 138 | else 139 | fBgColor = ViewColor(); 140 | 141 | fGradientHighlight.AddColor(tint_color(fBgColor, B_LIGHTEN_1_TINT), 0); 142 | fGradientHighlight.AddColor(tint_color(fBgColor, B_DARKEN_3_TINT), 255); 143 | 144 | fGradientPressed.AddColor(tint_color(fBgColor, B_DARKEN_1_TINT), 0); 145 | fGradientPressed.AddColor(tint_color(fBgColor, B_DARKEN_4_TINT), 255); 146 | 147 | fMarginColor = tint_color(fBgColor, B_DARKEN_2_TINT); 148 | } 149 | 150 | 151 | void 152 | ImageButton::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage) 153 | { 154 | 155 | switch (code) { 156 | case B_EXITED_VIEW: 157 | MakeFocus(false); 158 | fMouseState = MOUSE_OUTSIDE; 159 | Invalidate(); 160 | break; 161 | 162 | case B_ENTERED_VIEW: 163 | fMouseState = MOUSE_INSIDE; 164 | Invalidate(); 165 | break; 166 | 167 | default: 168 | break; 169 | } 170 | 171 | BButton::MouseMoved(where, code, dragMessage); 172 | } 173 | 174 | 175 | void 176 | ImageButton::MouseUp(BPoint where) 177 | { 178 | if (fTimer->MS() > fLongPushLimit) 179 | fLongPush = true; 180 | 181 | fMouseState = MOUSE_INSIDE; 182 | fShowFrame = false; 183 | fOffset = BPoint(0, 0); 184 | Invalidate(); 185 | BButton::MouseUp(where); 186 | } 187 | 188 | 189 | void 190 | ImageButton::MouseDown(BPoint where) 191 | { 192 | fTimer->Restart(); 193 | fMouseState = MOUSE_PRESSED; 194 | fLongPush = false; 195 | fShowFrame = true; 196 | fOffset = BPoint(1, 1); 197 | Invalidate(); 198 | BButton::MouseDown(where); 199 | } 200 | 201 | 202 | bool 203 | ImageButton::PushedLong(void) 204 | { 205 | return fLongPush; 206 | } 207 | 208 | void 209 | ImageButton::FrameResized(float newWidth, float newHeight) 210 | { 211 | BButton::FrameResized(newWidth, newHeight); 212 | 213 | int width = std::min(newWidth, newHeight) * fMarginProportion; 214 | fImageRect = BRect(0, 0, width, width); 215 | 216 | fImageRect.OffsetTo((newWidth - width)/2, (newHeight - width)/2); 217 | 218 | delete fBitmap; 219 | fBitmap = Tools::LoadBitmap(fImageName, fImageRect.Width()); 220 | if (fBitmap == nullptr) 221 | !out << "Bitmap == nullptr" << std::endl; 222 | Invalidate(); 223 | 224 | fGradientHighlight.SetEnd(0, newHeight); 225 | fGradientPressed.SetEnd(0, newHeight); 226 | } 227 | 228 | 229 | BBitmap* 230 | ImageButton::_RescaleBitmap(const BBitmap* src, int32 width, int32 height) 231 | { 232 | if (!src || !src->IsValid()) 233 | return nullptr; 234 | 235 | BRect srcSize = src->Bounds(); 236 | 237 | if (height < 0) { 238 | float srcProp = srcSize.Height()/srcSize.Width(); 239 | height = (int32)(width * ceil(srcProp)); 240 | } 241 | 242 | BBitmap* res = new BBitmap(BRect(0, 0, (float)width, (float)height), 243 | src->ColorSpace()); 244 | 245 | float dx = (srcSize.Width() + 1)/(float)(width + 1); 246 | float dy = (srcSize.Height() + 1)/(float)(height + 1); 247 | uint8 bpp = (uint8)(src->BytesPerRow()/ceil(srcSize.Width())); 248 | 249 | int srcYOff = src->BytesPerRow(); 250 | int dstYOff = res->BytesPerRow(); 251 | 252 | void* dstData = res->Bits(); 253 | void* srcData = src->Bits(); 254 | 255 | for (int32 y = 0; y <= height; y++) { 256 | void* dstRow = (void*)((uintptr_t)dstData + (uintptr_t)(y * dstYOff)); 257 | void* srcRow = (void*)((uintptr_t)srcData + ((uintptr_t)(y * dy) * srcYOff)); 258 | 259 | for (int32 x = 0; x <= width; x++) 260 | memcpy((void*)((uintptr_t)dstRow + (x * bpp)), (void*)((uintptr_t)srcRow 261 | + ((uintptr_t)(x * dx) * bpp)), bpp); 262 | } 263 | 264 | return res; 265 | } 266 | -------------------------------------------------------------------------------- /application/ImageButton.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2012 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #ifndef IMAGEBUTTON_H 10 | #define IMAGEBUTTON_H 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | 23 | 24 | #include "Debug.h" 25 | #include "Timer.h" 26 | 27 | class ImageButton : public BButton 28 | { 29 | public: 30 | ImageButton(BString imageName, BMessage *message = nullptr, 31 | float marginProportion = 0, int frameBehaviour = 0, 32 | const char* tooltip = NULL, 33 | const char* name = "im_button", 34 | uint32 flags = B_FRAME_EVENTS | B_WILL_DRAW 35 | | B_NAVIGABLE |B_FULL_UPDATE_ON_RESIZE 36 | | B_DRAW_ON_CHILDREN); 37 | 38 | virtual void Draw(BRect updateRect); 39 | virtual void AttachedToWindow(void); 40 | virtual void MouseMoved(BPoint where, uint32 code, 41 | const BMessage* dragMessage); 42 | virtual void MouseUp(BPoint where); 43 | virtual void MouseDown(BPoint where); 44 | 45 | virtual void FrameResized(float newWidth, float newHeight); 46 | 47 | bool PushedLong(void); 48 | 49 | private: 50 | BBitmap* _RescaleBitmap(const BBitmap* src, int32 width, 51 | int32 height); 52 | 53 | BString fImageName; 54 | BBitmap* fBitmap; 55 | BRect fImageRect; 56 | BPoint fOffset; 57 | float fMarginProportion; 58 | int fFrameBehaviour; 59 | 60 | BGradientLinear fGradientHighlight; 61 | BGradientLinear fGradientPressed; 62 | 63 | std::unique_ptr fTimer; 64 | 65 | rgb_color fBgColor; 66 | rgb_color fHighlightColor; 67 | rgb_color fButtonPressedColor; 68 | rgb_color fMarginColor; 69 | 70 | enum { 71 | MOUSE_OUTSIDE, MOUSE_INSIDE, MOUSE_PRESSED 72 | }; 73 | 74 | int fMouseState; 75 | bool fShowFrame; 76 | bool fLongPush; 77 | double fLongPushLimit; 78 | 79 | Debug out; 80 | }; 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /application/ImagePopUp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2011 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | 10 | #include "ImagePopUp.h" 11 | 12 | #include 13 | 14 | ImagePopUp::ImagePopUp(const char* name, const char* label, BMessage* message, 15 | uint32 flags) 16 | : 17 | BOptionControl(name, label, message, flags) 18 | { 19 | 20 | } 21 | 22 | 23 | ImagePopUp::~ImagePopUp() 24 | { 25 | 26 | } 27 | 28 | 29 | void 30 | ImagePopUp::Draw(BRect updateRect) 31 | { 32 | SetHighColor(255, 255, 255, 255); 33 | FillRect(Bounds()); 34 | } 35 | 36 | void 37 | ImagePopUp::MessageReceived(BMessage* message) 38 | { 39 | 40 | } 41 | 42 | 43 | status_t 44 | ImagePopUp::AddOption(const char* name, int32 value) 45 | { 46 | 47 | return 0; 48 | } 49 | 50 | 51 | bool 52 | ImagePopUp::GetOptionAt(int32 index, const char** _name, int32* _value) 53 | { 54 | 55 | return true; 56 | } 57 | 58 | 59 | void 60 | ImagePopUp::RemoveOptionAt(int32 index) 61 | { 62 | 63 | 64 | } 65 | 66 | 67 | int32 68 | ImagePopUp::CountOptions() const 69 | { 70 | 71 | return 0; 72 | } 73 | 74 | 75 | status_t 76 | ImagePopUp::AddOptionAt(const char* name, int32 value, int32 index) 77 | { 78 | 79 | return 0; 80 | } 81 | 82 | 83 | int32 84 | ImagePopUp::SelectedOption(const char** name, int32* outValue) const 85 | { 86 | 87 | return 0; 88 | } 89 | -------------------------------------------------------------------------------- /application/ImagePopUp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2011 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #ifndef IMAGEPOPUP_H 10 | #define IMAGEPOPUP_H 11 | 12 | #include 13 | #include 14 | 15 | class ImagePopUp : public BOptionControl 16 | { 17 | public: 18 | ImagePopUp(const char* name, 19 | const char* label, BMessage* message, 20 | uint32 flags = B_WILL_DRAW); 21 | virtual ~ImagePopUp(); 22 | 23 | virtual void Draw(BRect updateRect); 24 | 25 | virtual void MessageReceived(BMessage* message); 26 | 27 | status_t AddOption(const char* name, int32 value); 28 | virtual bool GetOptionAt(int32 index, const char** _name, 29 | int32* _value); 30 | virtual void RemoveOptionAt(int32 index); 31 | virtual int32 CountOptions() const; 32 | virtual status_t AddOptionAt(const char* name, int32 value, 33 | int32 index); 34 | virtual int32 SelectedOption(const char** name = nullptr, 35 | int32* outValue = nullptr) const; 36 | 37 | private: 38 | 39 | }; 40 | 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /application/ImageSpinner.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2012 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #include "ImageSpinner.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | 24 | #include 25 | 26 | #include "Messages.h" 27 | #include "Settings.h" 28 | #include "Tools.h" 29 | 30 | 31 | using namespace std; 32 | 33 | ImageSpinner::ImageSpinner(float const& imageHeight) 34 | : 35 | BGroupView("image_spinner", B_VERTICAL, 0), 36 | fImageHeight(imageHeight) 37 | { 38 | 39 | fBasicImageSpinner = new BasicImageSpinner; 40 | fBasicImageSpinner->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, fImageHeight + 6)); 41 | fBasicImageSpinner->SetExplicitMinSize(BSize(0, 0/*fImageHeight + 6*/)); 42 | 43 | fDeleteButton = new ImageButton("quit", 44 | new BMessage(M_DELETE), 0.3, 1, "Remove document"); 45 | fBackButton = new ImageButton("back", 46 | new BMessage(M_MOVE_LEFT), 0.3, 1, "Previous document"); 47 | fNextButton = new ImageButton("next", 48 | new BMessage(M_MOVE_RIGHT), 0.3, 1, "Next document"); 49 | fOpenButton = new ImageButton("open_document", 50 | new BMessage(MSG_OPEN_FILE_PANEL), 0.3, 1, "Open document"); 51 | 52 | 53 | BGroupLayout* navigationLayout = BLayoutBuilder::Group<>(B_HORIZONTAL, 0) 54 | .Add(fDeleteButton) 55 | .Add(fBackButton) 56 | .Add(fNextButton) 57 | .Add(fOpenButton, 10) 58 | //.AddStrut(12) 59 | ; 60 | 61 | navigationLayout->SetExplicitMinSize(BSize(0, 20)); 62 | navigationLayout->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 50)); 63 | 64 | auto scrollbar = new BScrollBar("h_scrollbar", 65 | fBasicImageSpinner, 0, 0, B_HORIZONTAL); 66 | scrollbar->SetSteps(200, 200); 67 | 68 | BLayoutBuilder::Group<>(this) 69 | .Add(scrollbar) 70 | .AddGlue(0) 71 | .Add(fBasicImageSpinner) 72 | //.AddStrut(10) 73 | .AddGlue(0) 74 | .Add(navigationLayout) 75 | .End() 76 | ; 77 | } 78 | 79 | 80 | void 81 | ImageSpinner::AttachedToWindow(void) 82 | { 83 | fDeleteButton->SetTarget(this); 84 | fBackButton->SetTarget(this); 85 | fNextButton->SetTarget(this); 86 | fBasicImageSpinner->MakeFocus(true); 87 | BGroupView::AttachedToWindow(); 88 | } 89 | 90 | 91 | void 92 | ImageSpinner::MakeFocus(bool focus) 93 | { 94 | BGroupView::MakeFocus(focus); 95 | fBasicImageSpinner->MakeFocus(focus); 96 | } 97 | 98 | void 99 | ImageSpinner::MessageReceived(BMessage* message) 100 | { 101 | switch (message->what) { 102 | case M_BACK: 103 | fBasicImageSpinner->Back(); 104 | break; 105 | 106 | case M_NEXT: 107 | fBasicImageSpinner->Next(); 108 | break; 109 | 110 | case M_DELETE: 111 | fBasicImageSpinner->RemoveSelectedItem(); 112 | break; 113 | 114 | case M_MOVE_LEFT: 115 | fBasicImageSpinner->MoveLeftSelectedItem(); 116 | break; 117 | 118 | case M_MOVE_RIGHT: 119 | fBasicImageSpinner->MoveRightSelectedItem(); 120 | break; 121 | 122 | default: 123 | BGroupView::MessageReceived(message); 124 | break; 125 | } 126 | } 127 | 128 | 129 | void 130 | ImageSpinner::Add(BString const& str, std::unique_ptr&& bitmap) 131 | { 132 | if (bitmap->Bounds().Height() != fImageHeight) { 133 | auto res = Tools::RescaleBitmap(move(bitmap), 0, fImageHeight); 134 | fBasicImageSpinner->Add(str, move(res)); 135 | } else { 136 | fBasicImageSpinner->Add(str, move(bitmap)); 137 | } 138 | } 139 | 140 | 141 | bool 142 | ImageSpinner::NeedsFile(BString const& filePath) 143 | { 144 | return fBasicImageSpinner->NeedsFile(filePath); 145 | } 146 | 147 | 148 | float 149 | ImageSpinner::PreferredImageHeight(void) 150 | { 151 | return fImageHeight; 152 | } 153 | 154 | 155 | BasicImageSpinner::BasicImageSpinner(void) 156 | : 157 | BView(BRect(), "basic_image_view", B_FOLLOW_ALL, 158 | B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS), 159 | fOldMousePos(0, 0), 160 | fMouseButtons(0), 161 | fSpace(5), 162 | fTotalWidth(fSpace), 163 | fIsPanning(false), 164 | fMaxItemsNumber(10), 165 | fCurrentIndex(0) 166 | { 167 | SetViewColor(B_TRANSPARENT_32_BIT); 168 | //SetDrawingMode(B_OP_ALPHA); 169 | //SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); 170 | 171 | 172 | fSettingsPath = Tools::SettingsPath(); 173 | 174 | _LoadSettings(); 175 | } 176 | 177 | 178 | BasicImageSpinner::~BasicImageSpinner() 179 | { 180 | _SaveSettings(); 181 | } 182 | 183 | 184 | void 185 | BasicImageSpinner::AttachedToWindow(void) 186 | { 187 | _AdaptScrollBarRange(); 188 | BView::AttachedToWindow(); 189 | } 190 | 191 | 192 | void 193 | BasicImageSpinner::Draw(BRect updateRect) 194 | { 195 | BRect bounds = Bounds(); 196 | SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 197 | FillRect(bounds); 198 | 199 | if (fItems.empty()) 200 | return; 201 | 202 | SetPenSize(2); 203 | SetHighColor(0, 0, 0, 255); 204 | 205 | float height = get<0>(fItems.front())->Bounds().Height(); 206 | 207 | BPoint offset(fSpace, (bounds.Height() - height) / 2); 208 | 209 | if (offset.y < 0) 210 | offset.y = 0; 211 | 212 | bool hasDrawn = false; 213 | uint32 index = 0; 214 | for (auto it = fItems.begin(); it != fItems.end(); ++it, ++index) { 215 | BBitmap* bitmap = (BBitmap*)(&*get<0>(*it)); 216 | auto rect = bitmap->Bounds().OffsetByCopy(offset); 217 | if (rect.Intersects(updateRect)) { 218 | hasDrawn = true; 219 | DrawBitmapAsync(bitmap, rect/*.LeftTop()*/); 220 | if (index == fCurrentIndex) { 221 | SetHighColor(0, 0, 255, 255); 222 | SetPenSize(3); 223 | StrokeRect(rect); 224 | SetPenSize(2); 225 | SetHighColor(0, 0, 0, 255); 226 | } else { 227 | StrokeRect(get<0>(*it)->Bounds().OffsetByCopy(offset)); 228 | } 229 | } else if (hasDrawn) { 230 | break; 231 | } 232 | offset.x += get<0>(*it)->Bounds().Width() + fSpace; 233 | } 234 | 235 | Sync(); 236 | BView::Draw(updateRect); 237 | } 238 | 239 | 240 | 241 | void 242 | BasicImageSpinner::KeyDown(const char* bytes, int32 numBytes) 243 | { 244 | if (numBytes == 1) { 245 | switch (bytes[0]) { 246 | case B_ENTER: 247 | _SelectIndex(fCurrentIndex); 248 | break; 249 | 250 | case B_DELETE: 251 | RemoveSelectedItem(); 252 | break; 253 | 254 | case B_DOWN_ARROW: case B_RIGHT_ARROW: 255 | _Next(); 256 | break; 257 | 258 | case B_UP_ARROW: case B_LEFT_ARROW: 259 | _Back(); 260 | break; 261 | 262 | case B_PAGE_UP: 263 | break; 264 | 265 | case B_PAGE_DOWN: 266 | break; 267 | 268 | case B_HOME: 269 | _First(); 270 | break; 271 | 272 | case B_END: 273 | _Last(); 274 | break; 275 | 276 | 277 | default: 278 | BView::KeyDown(bytes, numBytes); 279 | break; 280 | } 281 | } 282 | } 283 | 284 | 285 | 286 | void 287 | BasicImageSpinner::FrameResized(float newWidth, float newHeight) 288 | { 289 | 290 | _AdaptScrollBarRange(); 291 | BView::FrameResized(newWidth, newHeight); 292 | } 293 | 294 | 295 | void 296 | BasicImageSpinner::MessageReceived(BMessage* message) 297 | { 298 | 299 | BView::MessageReceived(message); 300 | } 301 | 302 | 303 | void 304 | BasicImageSpinner::MouseMoved(BPoint where, uint32 code, 305 | const BMessage* dragMessage) 306 | { 307 | switch (code) { 308 | case B_EXITED_VIEW: 309 | fIsPanning = false; 310 | break; 311 | 312 | default: 313 | break; 314 | } 315 | 316 | if (fIsPanning == true) { 317 | BPoint delta = fOldMousePos - where; 318 | 319 | ScrollBar(B_HORIZONTAL)->SetValue( 320 | ScrollBar(B_HORIZONTAL)->Value() + delta.x); 321 | } 322 | 323 | BView::MouseMoved(where, code, dragMessage); 324 | } 325 | 326 | 327 | void 328 | BasicImageSpinner::MouseDown(BPoint where) 329 | { 330 | MakeFocus(true); 331 | GetMouse(&fOldMousePos, &fMouseButtons); 332 | 333 | int32 clicks = 0; 334 | Window()->CurrentMessage()->FindInt32("clicks", &clicks); 335 | 336 | if (clicks == 2) { 337 | _Select(fOldMousePos); 338 | } else { 339 | _HighlightPosition(fOldMousePos); 340 | fIsPanning = true; 341 | } 342 | 343 | BView::MouseDown(where); 344 | } 345 | 346 | 347 | void 348 | BasicImageSpinner::MouseUp(BPoint where) 349 | { 350 | fIsPanning = false; 351 | 352 | BView::MouseUp(where); 353 | } 354 | 355 | 356 | bool 357 | BasicImageSpinner::NeedsFile(BString const& filePath) 358 | { 359 | for (auto it = fItems.begin(); it != fItems.end(); ++it) { 360 | if (filePath == get<1>(*it)) { 361 | auto temp = move(*it); 362 | fItems.remove(*it); 363 | fItems.push_front(move(temp)); 364 | return false; 365 | } 366 | } 367 | 368 | return true; 369 | } 370 | 371 | 372 | void 373 | BasicImageSpinner::Add(BString const& filePath, std::unique_ptr&& bitmap) 374 | { 375 | uniform_int_distribution distribution(0, 999); 376 | mt19937 engine(time(NULL)); //Mersenn twister 377 | auto generate = bind(distribution, engine); // RNG 378 | 379 | 380 | int idNumber; 381 | bool isInvalid; 382 | 383 | // generate a random Number, and make sure it's unique. 384 | do { 385 | isInvalid = false; 386 | idNumber = generate(); 387 | for (auto it = fItems.begin(); it != fItems.end(); ++it) { 388 | if (get<2>(*it) == idNumber) { 389 | isInvalid = true; 390 | break; 391 | } 392 | } 393 | } while (isInvalid); 394 | 395 | // save bitmap to disk 396 | BString settingsPath(Tools::SettingsPath()); 397 | BString path(settingsPath); 398 | path << idNumber; 399 | Tools::ExportBitmap(bitmap.get(), path); 400 | 401 | _Add(filePath, move(bitmap), idNumber); 402 | } 403 | 404 | 405 | void 406 | BasicImageSpinner::_Add(BString const& filePath, 407 | std::unique_ptr&& bitmap, int const& bitmapID) 408 | { 409 | fItems.push_front(tuple, BString, int> 410 | (move(bitmap), filePath, bitmapID)); 411 | 412 | fTotalWidth += get<0>(fItems.front())->Bounds().Width() + fSpace; 413 | 414 | if (fItems.size() > fMaxItemsNumber) 415 | RemoveBackItem(); 416 | 417 | _AdaptScrollBarRange(); 418 | } 419 | 420 | 421 | void 422 | BasicImageSpinner::MoveLeftSelectedItem(void) 423 | { 424 | if (fCurrentIndex < 1 || fItems.size() < 2) 425 | return; 426 | 427 | 428 | 429 | auto it = fItems.begin(); 430 | for (uint32 i = 1; i < fCurrentIndex; ++i) 431 | ++it; 432 | 433 | auto left = it; 434 | ++it; 435 | swap(*left, *it); 436 | _Back(); 437 | } 438 | 439 | 440 | void 441 | BasicImageSpinner::MoveRightSelectedItem(void) 442 | { 443 | if (fCurrentIndex > (fItems.size() - 2) 444 | || fItems.size() < 2) 445 | return; 446 | 447 | auto it = fItems.begin(); 448 | for (uint32 i = 0; i < fCurrentIndex; ++i) 449 | ++it; 450 | 451 | auto left = it; 452 | ++it; 453 | swap(*left, *it); 454 | 455 | _Next(); 456 | } 457 | 458 | 459 | void 460 | BasicImageSpinner::RemoveBackItem(void) 461 | { 462 | fTotalWidth -= (get<0>(fItems.back())->Bounds().Width() + fSpace); 463 | 464 | BString path(Tools::SettingsPath()); 465 | path << get<2>(fItems.back()); 466 | BEntry entry(path); 467 | entry.Remove(); 468 | fItems.pop_back(); 469 | _AdaptScrollBarRange(); 470 | Invalidate(); 471 | } 472 | 473 | 474 | void 475 | BasicImageSpinner::RemoveSelectedItem(void) 476 | { 477 | if (fItems.empty() || fCurrentIndex < 0) 478 | return; 479 | 480 | auto it = fItems.begin(); 481 | for (uint32 i = 0; i < fCurrentIndex; ++i) 482 | ++it; 483 | 484 | fTotalWidth -= (get<0>(*it)->Bounds().Width() + fSpace); 485 | 486 | BString path(Tools::SettingsPath()); 487 | path << get<2>(*it); 488 | BEntry entry(path); 489 | entry.Remove(); 490 | fItems.remove(*it); 491 | 492 | --fCurrentIndex; 493 | if (fCurrentIndex < 0) 494 | fCurrentIndex = 0; 495 | 496 | _AdaptScrollBarRange(); 497 | Invalidate(); 498 | } 499 | 500 | 501 | void 502 | BasicImageSpinner::_Select(BPoint const& pos) 503 | { 504 | float temp = 0; 505 | for (auto it = fItems.begin(); it != fItems.end(); ++it) { 506 | temp += get<0>(*it)->Bounds().Width() + fSpace; 507 | if (temp < pos.x) 508 | continue; 509 | 510 | BMessage msg(MSG_OPEN_FILE); 511 | msg.AddString("file", get<1>(*it)); 512 | Window()->PostMessage(&msg); 513 | _First(); 514 | break; 515 | } 516 | } 517 | 518 | 519 | void 520 | BasicImageSpinner::_HighlightPosition(BPoint const& pos) 521 | { 522 | float temp = 0; 523 | int counter = 0; 524 | for (auto it = fItems.begin(); it != fItems.end(); ++it, ++counter) { 525 | temp += get<0>(*it)->Bounds().Width() + fSpace; 526 | if (temp >= pos.x) 527 | break; 528 | } 529 | 530 | fCurrentIndex = counter; 531 | 532 | if (fCurrentIndex >= fItems.size()) 533 | fCurrentIndex = -1; 534 | 535 | Invalidate(); 536 | } 537 | 538 | 539 | void 540 | BasicImageSpinner::_SelectIndex(int const& index) 541 | { 542 | int counter = 0; 543 | for (auto it = fItems.begin(); it != fItems.end(); ++it) { 544 | if (counter < index) { 545 | ++counter; 546 | continue; 547 | } 548 | 549 | BMessage msg(MSG_OPEN_FILE); 550 | msg.AddString("file", get<1>(*it)); 551 | Window()->PostMessage(&msg); 552 | _First(); 553 | break; 554 | } 555 | } 556 | 557 | 558 | void 559 | BasicImageSpinner::_SaveSettings(void) 560 | { 561 | #if 0 // This is known to crash DocumentViewer in some cases, see issue #2 562 | BString settingsPath(Tools::SettingsPath()); 563 | BString path = settingsPath; 564 | path.Append("RecentlyOpened"); 565 | BFile file(path, B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); 566 | 567 | BString str; 568 | for (auto it = fItems.rbegin(); it != fItems.rend(); ++it) { 569 | str = get<1>(*it); 570 | str << "\t" << get<2>(*it) << "\n"; 571 | file.Write(str, str.Length()); 572 | } 573 | #endif 574 | } 575 | 576 | 577 | void 578 | BasicImageSpinner::_LoadSettings(void) 579 | { 580 | #if 0 // This is known to crash DocumentViewer in some cases, see issue #2 581 | BString settingsPath = Tools::SettingsPath(); 582 | BString path = settingsPath; 583 | path.Append("RecentlyOpened"); 584 | 585 | BFile file(path, B_READ_ONLY | B_CREATE_FILE); 586 | off_t size; 587 | file.GetSize(&size); 588 | char buffer[size]; 589 | file.Read(&buffer, size); 590 | 591 | fItems.clear(); 592 | BString str = ""; 593 | for (int i = 0; i < size; ++i) { 594 | if (buffer[i] != '\n') { 595 | str += buffer[i]; 596 | } else { 597 | auto vec = Tools::Split(str, '\t'); 598 | str = ""; 599 | if (vec.size() != 2) 600 | continue; 601 | 602 | path = settingsPath; 603 | path.Append(vec[1]); 604 | unique_ptr bitmap(BTranslationUtils::GetBitmap(path)); 605 | 606 | if (bitmap == nullptr) 607 | return; 608 | 609 | stringstream ss; 610 | ss << vec[1]; 611 | int idNumber; 612 | ss >>idNumber; 613 | _Add(vec[0], move(bitmap), idNumber); 614 | 615 | } 616 | } 617 | #endif 618 | } 619 | 620 | 621 | void 622 | BasicImageSpinner::_ScrollToSelection(void) 623 | { 624 | // ToDO : Not yet implemented 625 | 626 | Invalidate(); 627 | } 628 | 629 | 630 | void 631 | BasicImageSpinner::Next(void) 632 | { 633 | _Next(); 634 | } 635 | 636 | 637 | void 638 | BasicImageSpinner::_Next(void) 639 | { 640 | ++fCurrentIndex; 641 | if (fCurrentIndex < 0) 642 | fCurrentIndex = 0; 643 | else if (fCurrentIndex >= fItems.size()) 644 | fCurrentIndex = fItems.size() - 1; 645 | 646 | float width = fSpace; 647 | auto it = fItems.begin(); 648 | for (uint32 i = 0; i <= fCurrentIndex; ++i, ++it) 649 | width += get<0>(*it)->Bounds().Width() + fSpace; 650 | 651 | if (Bounds().right < width) 652 | ScrollTo(width - Bounds().Width(), 0); 653 | 654 | Invalidate(); 655 | } 656 | 657 | 658 | void 659 | BasicImageSpinner::_Back(void) 660 | { 661 | --fCurrentIndex; 662 | if (fCurrentIndex < 0) 663 | fCurrentIndex = 0; 664 | else if (fCurrentIndex >= fItems.size()) 665 | fCurrentIndex = fItems.size() - 1; 666 | 667 | float width = 0; 668 | auto it = fItems.begin(); 669 | for (uint32 i = 0; i < fCurrentIndex; ++i, ++it) 670 | width += get<0>(*it)->Bounds().Width() + fSpace; 671 | 672 | if (Bounds().left > width) 673 | ScrollTo(width, 0); 674 | 675 | Invalidate(); 676 | } 677 | 678 | 679 | void 680 | BasicImageSpinner::Back(void) 681 | { 682 | _Back(); 683 | } 684 | 685 | 686 | void 687 | BasicImageSpinner::_First(void) 688 | { 689 | fCurrentIndex = 0; 690 | Invalidate(); 691 | } 692 | 693 | 694 | void 695 | BasicImageSpinner::_Last(void) 696 | { 697 | fCurrentIndex = fItems.size() - 1; 698 | Invalidate(); 699 | } 700 | 701 | 702 | void 703 | BasicImageSpinner::_AdaptScrollBarRange(void) 704 | { 705 | float width = -Bounds().Width(); 706 | if (width > 0) 707 | return; 708 | 709 | width += fTotalWidth; 710 | auto scrollbar = ScrollBar(B_HORIZONTAL); 711 | scrollbar->SetRange(0, width); 712 | scrollbar->SetProportion(1 - width/fTotalWidth); 713 | } 714 | 715 | 716 | BString 717 | BasicImageSpinner::_RandomName(void) 718 | { 719 | uniform_int_distribution distribution(0,999); 720 | mt19937 engine(time(NULL)); //Mersenn twister 721 | auto random = bind(distribution, engine); // RNG 722 | 723 | BString str; 724 | str << random(); 725 | 726 | return str; 727 | } 728 | 729 | 730 | -------------------------------------------------------------------------------- /application/ImageSpinner.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2012 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #ifndef IMAGESPINNER_H 10 | #define IMAGESPINNER_H 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "Debug.h" 23 | #include "ImageButton.h" 24 | 25 | class BasicImageSpinner : public BView 26 | { 27 | public: 28 | BasicImageSpinner(void); 29 | virtual ~BasicImageSpinner(); 30 | 31 | virtual void AttachedToWindow(void); 32 | virtual void Draw(BRect updateRect); 33 | virtual void FrameResized(float newWidth, float newHeight); 34 | virtual void KeyDown(const char* bytes, int32 numBytes); 35 | virtual void MessageReceived(BMessage* message); 36 | virtual void MouseDown(BPoint where); 37 | virtual void MouseUp(BPoint where); 38 | virtual void MouseMoved(BPoint where, uint32 code, 39 | const BMessage* dragMessage); 40 | 41 | void Add(BString const& str, std::unique_ptr&& bitmap); 42 | 43 | void Next(void); 44 | void Back(void); 45 | 46 | bool NeedsFile(BString const& filePath); 47 | 48 | void RemoveBackItem(void); 49 | void RemoveSelectedItem(void); 50 | 51 | void MoveLeftSelectedItem(void); 52 | void MoveRightSelectedItem(void); 53 | 54 | private: 55 | void _AdaptScrollBarRange(void); 56 | void _Add(BString const& filePath, 57 | std::unique_ptr&& bitmap, int const& bitmapID); 58 | void _SaveSettings(void); 59 | void _LoadSettings(void); 60 | void _Last(void); 61 | void _Next(void); 62 | void _Back(void); 63 | void _First(void); 64 | void _HighlightPosition(BPoint const& pos); 65 | void _Select(BPoint const& pos); 66 | void _SelectIndex(int const& index); 67 | void _ScrollToSelection(void); 68 | 69 | BString _RandomName(void); 70 | 71 | 72 | std::list< std::tuple, BString, int> > fItems; 73 | 74 | BPoint fOldMousePos; 75 | uint32 fMouseButtons; 76 | 77 | float fSpace; 78 | float fTotalWidth; 79 | bool fIsPanning; 80 | uint32 fMaxItemsNumber; 81 | uint32 fCurrentIndex; 82 | BString fAppName; 83 | BString fSettingsPath; 84 | 85 | 86 | Debug out; 87 | }; 88 | 89 | class ImageSpinner : public BGroupView 90 | { 91 | public: 92 | ImageSpinner(float const& imageHeight = 500); 93 | virtual void MakeFocus(bool focus); 94 | virtual void MessageReceived(BMessage* message); 95 | virtual void AttachedToWindow(void); 96 | 97 | void Add(BString const& filePath, std::unique_ptr&& bitmap); 98 | 99 | bool NeedsFile(BString const& filePath); 100 | 101 | float PreferredImageHeight(void); 102 | 103 | private: 104 | 105 | ImageButton* fDeleteButton; 106 | ImageButton* fBackButton; 107 | ImageButton* fNextButton; 108 | ImageButton* fOpenButton; 109 | 110 | 111 | BasicImageSpinner* fBasicImageSpinner; 112 | 113 | float fImageHeight; 114 | 115 | enum { 116 | M_BACK = 'ib01', M_NEXT = 'in01', 117 | M_MOVE_LEFT = 'im01', M_MOVE_RIGHT = 'im02', 118 | M_DELETE = 'id01' 119 | }; 120 | 121 | }; 122 | 123 | #endif // IMAGESPINNER_H 124 | -------------------------------------------------------------------------------- /application/ImageTabView.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2011 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #include "ImageTabView.h" 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include "Tools.h" 18 | 19 | ImageTab::ImageTab(const char* imgName, BView* tabView) 20 | : 21 | BTab(tabView) 22 | { 23 | fBitmap = nullptr; 24 | fImageName.SetTo(imgName); 25 | } 26 | 27 | 28 | void 29 | ImageTab::DrawLabel(BView* owner, BRect frame) 30 | { 31 | 32 | int size = std::min(frame.Width(), frame.Height()) - 2; 33 | 34 | if (fBitmap == nullptr) { 35 | fBitmap = Tools::LoadBitmap(fImageName, size); 36 | } else if (fBitmap->Bounds().Height() != size) { 37 | delete fBitmap; 38 | fBitmap = Tools::LoadBitmap(fImageName, size); 39 | } 40 | 41 | owner->SetDrawingMode(B_OP_OVER); 42 | 43 | BPoint where; 44 | where.x = frame.left + (frame.Width() - fBitmap->Bounds().Width()) / 2; 45 | where.y = frame.top + (frame.Height() - fBitmap->Bounds().Height())/ 2; 46 | 47 | owner->DrawBitmap(fBitmap, where); 48 | } 49 | 50 | 51 | ImageTabView::ImageTabView(const char* name) 52 | : 53 | BTabView(name), 54 | fTabWidth(38) 55 | { 56 | SetTabHeight(26); 57 | } 58 | 59 | 60 | BRect 61 | ImageTabView::TabFrame(int32 index) const 62 | { 63 | if (index < 0 || index > CountTabs()) 64 | return BRect(); 65 | 66 | return BRect(index*fTabWidth, 0, (index + 1) * fTabWidth, TabHeight()); 67 | } 68 | 69 | void 70 | ImageTabView::MouseMoved(BPoint where, uint32 code, const BMessage * dragMessage) 71 | { 72 | int32 numTabs = CountTabs(); 73 | if (code == B_INSIDE_VIEW || code == B_ENTERED_VIEW) { 74 | for (int i = 0; i < numTabs; i++) { 75 | const BRect tabRect = TabFrame(i); 76 | if (tabRect.Contains(where)) { 77 | SetToolTip(TabAt(i)->Label()); 78 | } 79 | } 80 | } else { 81 | SetToolTip(""); 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /application/ImageTabView.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2011 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #ifndef IMAGETAB_H 10 | #define IMAGETAB_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include "Debug.h" 17 | 18 | class ImageTab : public BTab 19 | { 20 | public: 21 | ImageTab(const char* imageName, BView* tabView = nullptr); 22 | virtual void DrawLabel(BView* owner, BRect frame); 23 | 24 | private: 25 | BBitmap* fBitmap; 26 | Debug out; 27 | BString fImageName; 28 | }; 29 | 30 | 31 | class ImageTabView : public BTabView 32 | { 33 | public: 34 | ImageTabView(const char* name = "im_tabview"); 35 | virtual BRect TabFrame(int32 index) const; 36 | virtual void MouseMoved(BPoint where, uint32 code, const BMessage * dragMessage); 37 | 38 | 39 | private: 40 | float fTabWidth; 41 | }; 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /application/MainApplication.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2011 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #ifndef MAINAPPLICATION_H 10 | #define MAINAPPLICATION_H 11 | 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include "Debug.h" 18 | #include "MainWindow.h" 19 | #include "Messages.h" 20 | #include "PDFFilter.h" 21 | 22 | class MainApplication : public BApplication 23 | { 24 | public: 25 | MainApplication(void) 26 | : 27 | BApplication("application/x-vnd.documentviewer") 28 | { 29 | fFilePanel = nullptr; 30 | fMainWindow = nullptr; 31 | } 32 | 33 | virtual void ReadyToRun(void) 34 | { 35 | if (fMainWindow == nullptr) 36 | fMainWindow = new MainWindow(); 37 | } 38 | 39 | virtual void RefsReceived(BMessage* msg) 40 | { 41 | uint32 type = 0; 42 | int32 count = 0; 43 | 44 | msg->GetInfo ("refs", &type, &count); 45 | if (type != B_REF_TYPE) 46 | return; 47 | 48 | if (fMainWindow == nullptr) 49 | fMainWindow = new MainWindow(); 50 | 51 | entry_ref ref; 52 | for (int32 i = --count; i >= 0; --i) 53 | if (msg->FindRef("refs", i, &ref) == B_OK) { 54 | BEntry entry(&ref, true); 55 | BPath path; 56 | entry.GetPath(&path); 57 | 58 | int32 page = 0; 59 | msg->FindInt32("page", &page); 60 | 61 | BString password = ""; 62 | msg->FindString("password", &password); 63 | 64 | BMessage message(MSG_OPEN_FILE); 65 | message.AddString("file", path.Path()); 66 | message.AddString("password", password); 67 | message.AddInt32("page", page); 68 | fMainWindow->PostMessage(&message); 69 | } 70 | } 71 | 72 | virtual void ArgvReceived (int32 argc, char **argv) 73 | { 74 | // check command line 75 | if (!(argc == 2 || argc == 3 || argc == 4)) 76 | exit(1); 77 | 78 | BString path = ""; 79 | if (argc >= 2) 80 | path = argv[1]; 81 | 82 | int page = 0; 83 | if (argc >= 3) 84 | page = atoi(argv[2]) - 1; 85 | 86 | BString password = ""; 87 | if (argc == 4) 88 | password = argv[3]; 89 | 90 | entry_ref ref; 91 | get_ref_for_path (path.String(), &ref); 92 | 93 | BMessage msg(B_REFS_RECEIVED); 94 | msg.AddRef("refs", &ref); 95 | msg.AddString("password", password); 96 | msg.AddInt32 ("page", page); 97 | PostMessage(&msg); 98 | } 99 | 100 | void MessageReceived(BMessage* msg) 101 | { 102 | switch (msg->what) { 103 | /* case B_CANCEL: 104 | if (fMainWindow == nullptr) 105 | PostMessage (B_QUIT_REQUESTED); 106 | 107 | break; 108 | */ 109 | default: 110 | BApplication::MessageReceived(msg); 111 | } 112 | } 113 | 114 | void OpenFilePanel(void) 115 | { 116 | if (fFilePanel == nullptr) 117 | fFilePanel = new BFilePanel (B_OPEN_PANEL, 118 | nullptr, nullptr, B_FILE_NODE, true, nullptr, &fPDFFilter); 119 | 120 | fFilePanel->Show(); 121 | } 122 | 123 | private: 124 | MainWindow* fMainWindow; 125 | BFilePanel* fFilePanel; 126 | bool fToOpenFilePanel; 127 | PDFFilter fPDFFilter; 128 | 129 | Debug out; 130 | }; 131 | 132 | #endif 133 | -------------------------------------------------------------------------------- /application/MainWindow.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2011 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #include "MainWindow.h" 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include "MainApplication.h" 35 | #include "Messages.h" 36 | #include "Settings.h" 37 | #include "Tools.h" 38 | 39 | 40 | 41 | MainWindow::MainWindow(void) 42 | : 43 | BWindow(BRect(), "DocumentViewer", B_DOCUMENT_WINDOW_LOOK, 44 | B_NORMAL_WINDOW_FEEL, B_ASYNCHRONOUS_CONTROLS 45 | | B_QUIT_ON_WINDOW_CLOSE), 46 | fFullscreenIsOn(false), 47 | fPassword("") 48 | { 49 | fTabView1 = new ImageTabView("tab_view1"); 50 | 51 | fPreviewView = new PreviewView(); 52 | ImageTab* previewViewTab = new ImageTab("preview"); 53 | fTabView1->AddTab(fPreviewView, previewViewTab); 54 | previewViewTab->SetLabel("Preview"); 55 | 56 | 57 | fOutlineView = new OutlineView(); 58 | ImageTab* outlineViewTab = new ImageTab("outline"); 59 | fTabView1->AddTab(fOutlineView, outlineViewTab); 60 | outlineViewTab->SetLabel("Outline"); 61 | 62 | fSearchView = new SearchView(); 63 | ImageTab* searchViewTab = new ImageTab("find"); 64 | fTabView1->AddTab(fSearchView, searchViewTab); 65 | searchViewTab->SetLabel("Find"); 66 | 67 | fTabView1->Select(0); 68 | fDocumentView = new DocumentView("", "", fPassword); 69 | fRibbon = new MainWindowRB(); 70 | 71 | fDocumentLayout = BLayoutBuilder::Group<>(B_VERTICAL, 0) 72 | .AddSplit(B_HORIZONTAL, 0, 7).GetSplitView(&fSplitView1) 73 | .AddGroup(B_VERTICAL, 0, 1) 74 | .Add(fTabView1) 75 | .End() 76 | .AddSplit(B_VERTICAL, 0, 6).GetSplitView(&fSplitView2) 77 | .Add(fRibbon, 1) 78 | .AddGroup(B_VERTICAL, 0, 6) 79 | .Add(fDocumentView) 80 | .End() 81 | .End() 82 | .End() 83 | ; 84 | 85 | fImageSpinner = new ImageSpinner(); 86 | 87 | fIntroLayout = BLayoutBuilder::Group<>(B_VERTICAL, 0) 88 | .Add(fImageSpinner) 89 | .AddGlue(0) 90 | ; 91 | 92 | fCardLayout = new BCardLayout(); 93 | 94 | BLayoutBuilder::Group<>(this, B_VERTICAL, 0) 95 | .Add(fCardLayout) 96 | ; 97 | 98 | fCardLayout->AddItem(fIntroLayout); 99 | fCardLayout->AddItem(fDocumentLayout); 100 | fCardLayout->SetVisibleItem(fIntroLayout); 101 | _LoadSettings(); 102 | ResizeTo(1200, 600); ///Show 3 documents and minimize empty space 103 | Show(); 104 | } 105 | 106 | 107 | void 108 | MainWindow::MessageReceived(BMessage* message) 109 | { 110 | switch (message->what) { 111 | case MSG_NO_FIT: 112 | case MSG_NO_ZOOM: 113 | case MSG_FIT_PAGE_HEIGHT: 114 | case MSG_FIT_PAGE_WIDTH: 115 | case MSG_ZOOM_IN: 116 | case MSG_ZOOM_OUT: 117 | PostMessage(message, fDocumentView); 118 | break; 119 | 120 | case MSG_ACTIVE_PAGE: 121 | { 122 | PostMessage(message, fRibbon); 123 | int32 pageNumber = 0; 124 | message->FindInt32("info", &pageNumber); 125 | fPreviewView->SelectPage(pageNumber); 126 | break; 127 | } 128 | 129 | case MSG_GOTO_PAGE: 130 | { 131 | PostMessage(message, fDocumentView); 132 | PostMessage(message, fRibbon); 133 | 134 | int32 pageNumber = 0; 135 | message->FindInt32("info", &pageNumber); 136 | fPreviewView->SelectPage(pageNumber); 137 | break; 138 | } 139 | 140 | case MSG_FULLSCREEN: 141 | fFullscreenIsOn = !fFullscreenIsOn; 142 | 143 | if (fFullscreenIsOn) { 144 | fSavedFrame = Frame(); 145 | BScreen screen(this); 146 | BRect rect(screen.Frame()); 147 | MoveTo(rect.left, rect.top); 148 | ResizeTo(rect.Width(), rect.Height()); 149 | } else { 150 | Hide(); 151 | MoveTo(fSavedFrame.left, fSavedFrame.top); 152 | ResizeTo(fSavedFrame.Width(), fSavedFrame.Height()); 153 | Show(); 154 | } 155 | break; 156 | 157 | case MSG_APP_QUIT: 158 | { 159 | fCardLayout->SetVisibleItem((BLayoutItem*)fIntroLayout); 160 | fImageSpinner->MakeFocus(true); 161 | SetTitle("DocumentViewer"); 162 | ResizeTo(1200, 600); //Show 3 documents and minimize empty space 163 | //be_app->PostMessage(B_QUIT_REQUESTED); 164 | break; 165 | } 166 | 167 | case MSG_HELP: 168 | { 169 | BPathFinder pathFinder; 170 | BPath path; 171 | 172 | pathFinder.FindPath(B_FIND_PATH_DOCUMENTATION_DIRECTORY, 173 | "packages/documentviewer/help.pdf", B_FIND_PATH_EXISTING_ONLY, path); 174 | 175 | _OpenFile(path.Path(), "pdf", "", 0); 176 | break; 177 | } 178 | 179 | 180 | case MSG_HIGHLIGHT_RECT: 181 | PostMessage(message, fDocumentView); 182 | break; 183 | 184 | case MSG_SUPPORT: 185 | { 186 | char const* args[] = {"http://haikuarchives.github.io/DocumentViewer/support.html", 0}; 187 | be_roster->Launch("text/html", 1, args); 188 | break; 189 | } 190 | 191 | case MSG_PRINT_DOCUMENT: 192 | { 193 | fDocumentView->Print(); 194 | break; 195 | } 196 | 197 | 198 | case MSG_SETUP_PRINTER: 199 | { 200 | BPrintJob job("document's name"); 201 | job.ConfigPage(); 202 | break; 203 | } 204 | 205 | case MSG_OPEN_FILE_PANEL: 206 | case M_OPEN_FILE_PANEL: 207 | ((MainApplication*)be_app)->OpenFilePanel(); 208 | break; 209 | 210 | case MSG_OPEN_FILE: 211 | { 212 | BString file; 213 | message->FindString("file", &file); 214 | BString password = ""; 215 | message->FindString("password", &password); 216 | int32 page = 0; 217 | message->FindInt32("page", &page); 218 | auto type = _FileType(file); 219 | _OpenFile(file, type, password, page); 220 | break; 221 | } 222 | 223 | case M_SHOW_DOCUMENT: 224 | fCardLayout->SetVisibleItem((BLayoutItem*)fDocumentLayout); 225 | break; 226 | 227 | 228 | default: 229 | BWindow::MessageReceived(message); 230 | break; 231 | } 232 | } 233 | 234 | 235 | BString 236 | MainWindow::_FileType(BString const& file) 237 | { 238 | entry_ref ref; 239 | BEntry(file).GetRef(&ref); 240 | 241 | BMimeType mime; 242 | BMimeType::GuessMimeType(&ref, &mime); 243 | BMessage msg; 244 | uint32 i=0; 245 | mime.GetFileExtensions(&msg); 246 | 247 | BString type; 248 | while (true) { 249 | if (msg.FindString("extensions", i++, &type) != B_OK) 250 | break; 251 | 252 | if (type == "djvu" || type == "pdf" || type == "xps") 253 | break; 254 | } 255 | 256 | // hack, delte later, after types are added to haiku 257 | if (type == "") { 258 | if (file.IFindLast("djvu") != B_ERROR) 259 | type = "djvu"; 260 | if (file.IFindLast("xps") != B_ERROR) 261 | type = "xps"; 262 | } 263 | 264 | return type; 265 | } 266 | 267 | 268 | void 269 | MainWindow::_OpenFile(BString const& path, BString const& fileType, 270 | BString password, int32 const& page) 271 | { 272 | SetTitle(path); 273 | try { 274 | fDocumentView->FileChanged(path, fileType, password); 275 | fPreviewView->FileChanged(path, fileType, password); 276 | } catch(...) { 277 | BAlert* alert = new BAlert("error", "Can't open the file!", "OK"); 278 | alert->Go(); 279 | return; 280 | } 281 | fOutlineView->EngineChanged(fPreviewView->Engine()); 282 | fSearchView->EngineChanged(fPreviewView->Engine()); 283 | fRibbon->SetDocumentPages(fDocumentView->PageCount()); 284 | 285 | if (fImageSpinner->NeedsFile(path)) { 286 | auto height = fImageSpinner->PreferredImageHeight(); 287 | fImageSpinner->Add(path, move(fDocumentView->Cover(height))); 288 | } 289 | 290 | BMessage msg(MSG_GOTO_PAGE); 291 | msg.AddInt32("info", page); 292 | PostMessage(&msg); 293 | 294 | fCardLayout->SetVisibleItem((BLayoutItem*)fDocumentLayout); 295 | fDocumentView->MakeFocus(true); 296 | } 297 | 298 | 299 | /* 300 | void 301 | MainWindow::_AddDocumentLayout 302 | { 303 | fDocumentLayout = BLayoutBuilder::Group<>(B_VERTICAL, 0) 304 | .AddSplit(B_HORIZONTAL, 0, 7).GetSplitView(&fSplitView1) 305 | .AddGroup(B_VERTICAL, 0, 6) 306 | .Add(fTabView1) 307 | .End() 308 | .AddSplit(B_VERTICAL, 0, 1).GetSplitView(&fSplitView2) 309 | .Add(fRibbon, 1) 310 | .AddGroup(B_VERTICAL, 0, 6) 311 | .Add(fDocumentView) 312 | .End() 313 | .End() 314 | .End() 315 | ; 316 | } 317 | 318 | */ 319 | 320 | void 321 | MainWindow::_SaveSettings(void) 322 | { 323 | if (fFullscreenIsOn == false) 324 | fSavedFrame = Frame(); 325 | 326 | Settings settings("MainWindow"); 327 | 328 | settings << "SavedFrame" << fSavedFrame; 329 | 330 | if (fDocumentLayout != nullptr) { 331 | settings 332 | << "Split10" << fSplitView1->ItemWeight((int32)0) 333 | << "Split11" << fSplitView1->ItemWeight(1) 334 | << "Split20" << fSplitView2->ItemWeight((int32)0) 335 | << "Split21" << fSplitView2->ItemWeight(1) 336 | << "RibbonTab" << fRibbon->ActiveTab() 337 | << "SidebarTab" << fTabView1->Selection() 338 | << "Fullscreen" << (int32)fFullscreenIsOn 339 | << std::endl; 340 | } 341 | } 342 | 343 | 344 | void 345 | MainWindow::_LoadSettings() 346 | { 347 | Settings settings("MainWindow"); 348 | 349 | settings << "SavedFrame" >> fSavedFrame; 350 | 351 | if (fSavedFrame == BRect()) { 352 | Zoom(); 353 | } else { 354 | MoveTo(fSavedFrame.left, fSavedFrame.top); 355 | ResizeTo(fSavedFrame.Width(), fSavedFrame.Height()); 356 | } 357 | 358 | if (fDocumentLayout == nullptr) 359 | return; 360 | 361 | float weight; 362 | weight = 1.0; 363 | settings << "Split10" >> weight; 364 | fSplitView1->SetItemWeight(0, weight, true); 365 | if (weight == 0) 366 | fSplitView1->SetItemCollapsed(0, false); 367 | 368 | weight = 5.0; 369 | settings << "Split11" >> weight; 370 | fSplitView1->SetItemWeight(1, weight, true); 371 | if (weight == 0) 372 | fSplitView1->SetItemCollapsed(1, false); 373 | 374 | weight = 1.0; 375 | settings << "Split20" >> weight; 376 | fSplitView2->SetItemWeight(0, weight, true); 377 | if (weight == 0) 378 | fSplitView2->SetItemCollapsed(0, false); 379 | 380 | weight = 6.0; 381 | settings << "Split21" >> weight; 382 | fSplitView2->SetItemWeight(1, weight, true); 383 | if (weight == 0) 384 | fSplitView2->SetItemCollapsed(1, false); 385 | 386 | int32 value; 387 | value = 0; 388 | settings << "RibbonTab" >> value; 389 | fRibbon->SetActiveTab(value); 390 | value = 0; 391 | settings << "SidebarTab" >> value; 392 | fTabView1->Select(value); 393 | value = 0; 394 | settings << "Fullscreen" >> value; 395 | if (value != 0) 396 | PostMessage(MSG_FULLSCREEN); 397 | } 398 | 399 | 400 | bool 401 | MainWindow::QuitRequested(void) 402 | { 403 | Hide(); 404 | _SaveSettings(); 405 | return true; 406 | } 407 | -------------------------------------------------------------------------------- /application/MainWindow.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2011 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #ifndef MAINWINDOW_H 10 | #define MAINWINDOW_H 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | 24 | #include "BookmarksView.h" 25 | #include "Debug.h" 26 | #include "ImageSpinner.h" 27 | #include "ImageTabView.h" 28 | #include "MainWindowRB.h" 29 | #include "OutlineView.h" 30 | #include "DocumentView.h" 31 | #include "PreviewView.h" 32 | #include "SearchView.h" 33 | 34 | class MainWindow : public BWindow 35 | { 36 | public: 37 | MainWindow(void); 38 | virtual void MessageReceived(BMessage* message); 39 | virtual bool QuitRequested(void); 40 | 41 | const int& CurrentPageNumber(void) 42 | { 43 | return fDocumentView->CurrentPageNumber(); 44 | } 45 | 46 | 47 | enum{ M_EXIT = 'ie01', M_OPEN_FILE = 'io01', M_OPEN_FILE_PANEL, 48 | M_SHOW_DOCUMENT = 'is01' 49 | }; 50 | 51 | private: 52 | void _OpenFile(const BString& path, BString const& fileType, 53 | BString password, int32 const& page = 0); 54 | void _SaveSettings(void); 55 | void _LoadSettings(void); 56 | 57 | BString _FileType(BString const& file); 58 | 59 | BCardLayout* fCardLayout; 60 | BGroupLayout* fDocumentLayout; 61 | BGroupLayout* fIntroLayout; 62 | 63 | BSplitView* fSplitView1; 64 | BSplitView* fSplitView2; 65 | BSplitView* fSplitView3; 66 | BSplitView* fSplitView4; 67 | 68 | BButton* fButton; 69 | 70 | ImageTabView* fTabView1; 71 | 72 | DocumentView* fDocumentView; 73 | OutlineView* fOutlineView; 74 | PreviewView* fPreviewView; 75 | BookmarksView* fBookmarksView; 76 | SearchView* fSearchView; 77 | MainWindowRB* fRibbon; 78 | 79 | ImageSpinner* fImageSpinner; 80 | 81 | BRect fSavedFrame; 82 | 83 | bool fFullscreenIsOn; 84 | 85 | BString fPassword; 86 | 87 | Debug out; 88 | }; 89 | 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /application/MainWindowRB.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2011 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #include "MainWindowRB.h" 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "Messages.h" 22 | 23 | using namespace std; 24 | 25 | MainWindowRB::MainWindowRB(void) 26 | : 27 | BGroupView("main_widow_ribbon", B_VERTICAL, 0), 28 | fPages(0), 29 | fMaxHeight(35), 30 | fAutohiding(false) 31 | { 32 | SetFlags(Flags() | B_FULL_POINTER_HISTORY); 33 | 34 | unique_ptr navigationMessage(new BMessage(M_PAGENUMBER)); 35 | fPageNavigationView = new PageNavigationView(move(navigationMessage)); 36 | 37 | ImageButton* printButton = new ImageButton("print", 38 | new BMessage(MSG_PRINT_DOCUMENT), 0.3, 1, "Print document"); 39 | printButton->SetExplicitMinSize(BSize(fMaxHeight, fMaxHeight)); 40 | printButton->SetExplicitMaxSize(BSize(fMaxHeight, fMaxHeight)); 41 | 42 | fOpenFileButton = new ImageButton("open_document", 43 | new BMessage(MSG_OPEN_FILE_PANEL), 0.3, 1, "Open document"); 44 | fOpenFileButton->SetExplicitMinSize(BSize(fMaxHeight, fMaxHeight)); 45 | fOpenFileButton->SetExplicitMaxSize(BSize(fMaxHeight, fMaxHeight)); 46 | 47 | fQuitButton = new ImageButton("quit", new BMessage(MSG_APP_QUIT), 48 | 0.3, 1, "Close document"); 49 | fQuitButton->SetExplicitMinSize(BSize(fMaxHeight, 0)); 50 | fQuitButton->SetExplicitMaxSize(BSize(fMaxHeight, fMaxHeight)); 51 | 52 | // Home Tab 53 | BGroupLayout* homeLayout = BGroupLayoutBuilder(B_HORIZONTAL, 0) 54 | .SetInsets(2, 2, 2, 2) 55 | .Add(fPageNavigationView) 56 | .AddGlue(1000) 57 | .Add(printButton) 58 | .Add(fOpenFileButton) 59 | .Add(fQuitButton) 60 | .RootLayout() 61 | ; 62 | 63 | ImageButton* fullscreenButton = new ImageButton("fullscreen", 64 | new BMessage(MSG_FULLSCREEN) , 0.3, 1, "Fullscreen"); 65 | fullscreenButton->SetExplicitMinSize(BSize(fMaxHeight, 0)); 66 | fullscreenButton->SetExplicitMaxSize(BSize(fMaxHeight, fMaxHeight)); 67 | 68 | ImageButton* fitPageHeight = new ImageButton("fit_page_height", 69 | new BMessage(MSG_FIT_PAGE_HEIGHT), 0.3, 1, "Fit to height"); 70 | fitPageHeight->SetExplicitMinSize(BSize(fMaxHeight, fMaxHeight)); 71 | fitPageHeight->SetExplicitMaxSize(BSize(fMaxHeight, fMaxHeight)); 72 | 73 | ImageButton* fitPageWidth = new ImageButton("fit_page_width", 74 | new BMessage(MSG_FIT_PAGE_WIDTH), 0.3, 1, "Fit to width"); 75 | fitPageWidth->SetExplicitMinSize(BSize(fMaxHeight, fMaxHeight)); 76 | fitPageWidth->SetExplicitMaxSize(BSize(fMaxHeight, fMaxHeight)); 77 | 78 | ImageButton* zoomOriginal = new ImageButton("zoom_original", 79 | new BMessage(MSG_NO_ZOOM), 0.3, 1, "Reset zoom"); 80 | zoomOriginal->SetExplicitMinSize(BSize(fMaxHeight, fMaxHeight)); 81 | zoomOriginal->SetExplicitMaxSize(BSize(fMaxHeight, fMaxHeight)); 82 | 83 | ImageButton* zoomOut = new ImageButton("zoom_out", 84 | new BMessage(MSG_ZOOM_OUT), 0.3, 1, "Zoom out"); 85 | zoomOut->SetExplicitMinSize(BSize(fMaxHeight, fMaxHeight)); 86 | zoomOut->SetExplicitMaxSize(BSize(fMaxHeight, fMaxHeight)); 87 | 88 | ImageButton* zoomIn = new ImageButton("zoom_in", 89 | new BMessage(MSG_ZOOM_IN), 0.3, 1, "Zoom in"); 90 | zoomIn->SetExplicitMinSize(BSize(fMaxHeight, fMaxHeight)); 91 | zoomIn->SetExplicitMaxSize(BSize(fMaxHeight, fMaxHeight)); 92 | 93 | ImageButton* rotateLeftButton = new ImageButton("rotate_left", nullptr, 94 | 0.3, 1, "Rotate left"); 95 | rotateLeftButton->SetExplicitMinSize(BSize(fMaxHeight, fMaxHeight)); 96 | rotateLeftButton->SetExplicitMaxSize(BSize(fMaxHeight, fMaxHeight)); 97 | 98 | ImageButton* rotateRightButton = new ImageButton("rotate_right", nullptr, 99 | 0.3, 1, "Rotate right"); 100 | rotateRightButton->SetExplicitMinSize(BSize(fMaxHeight, fMaxHeight)); 101 | rotateRightButton->SetExplicitMaxSize(BSize(fMaxHeight, fMaxHeight)); 102 | 103 | // View Tab 104 | BGroupLayout* viewLayout = BGroupLayoutBuilder(B_HORIZONTAL, 0) 105 | .SetInsets(2, 2, 2, 2) 106 | .AddGroup(B_VERTICAL, 0, 0) 107 | .AddGroup(B_HORIZONTAL, 0, 0) 108 | .Add(fullscreenButton) 109 | .Add(new BSeparatorView(B_VERTICAL)) 110 | .Add(fitPageHeight) 111 | .Add(fitPageWidth) 112 | .Add(new BSeparatorView(B_VERTICAL)) 113 | .Add(zoomOriginal) 114 | .Add(zoomOut) 115 | .Add(zoomIn) 116 | .Add(new BSeparatorView(B_VERTICAL)) 117 | .Add(rotateLeftButton) 118 | .Add(rotateRightButton) 119 | .AddGlue(0) 120 | .End() 121 | .End() 122 | .RootLayout() 123 | ; 124 | 125 | // Edit Tab 126 | BGroupLayout* editLayout = BGroupLayoutBuilder(B_VERTICAL, 0) 127 | .AddGlue(0) 128 | //.Add(new ImageButton("star_green", nullptr, 0.3)) 129 | .AddGlue(0) 130 | .RootLayout() 131 | ; 132 | 133 | 134 | ImageButton* setupPrinterButton = new ImageButton("printer", 135 | new BMessage(MSG_SETUP_PRINTER), 0.3, 1, "Printer setup"); 136 | setupPrinterButton->SetExplicitMinSize(BSize(fMaxHeight, fMaxHeight)); 137 | setupPrinterButton->SetExplicitMaxSize(BSize(fMaxHeight, fMaxHeight)); 138 | 139 | // Configure Tab 140 | BGroupLayout* configureLayout = BGroupLayoutBuilder(B_HORIZONTAL, 0) 141 | .Add(setupPrinterButton) 142 | .AddGlue(0) 143 | .RootLayout() 144 | ; 145 | 146 | ImageButton* helpButton = new ImageButton("help2", 147 | new BMessage(MSG_HELP), 0.3, 1, "Help"); 148 | helpButton->SetExplicitMinSize(BSize(fMaxHeight, fMaxHeight)); 149 | helpButton->SetExplicitMaxSize(BSize(fMaxHeight, fMaxHeight)); 150 | 151 | ImageButton* supportButton = new ImageButton("support", 152 | new BMessage(MSG_SUPPORT), 0.3, 1, "Contribute"); 153 | supportButton->SetExplicitMinSize(BSize(fMaxHeight, fMaxHeight)); 154 | supportButton->SetExplicitMaxSize(BSize(fMaxHeight, fMaxHeight)); 155 | 156 | 157 | // Configure Tab 158 | BGroupLayout* helpLayout = BGroupLayoutBuilder(B_HORIZONTAL, 0) 159 | .Add(helpButton) 160 | .AddGlue(1000) 161 | .Add(supportButton) 162 | //.AddGlue(0) 163 | .RootLayout() 164 | ; 165 | 166 | fTabView = new ImageTabView("tab_view"); 167 | //fTabView->SetTabWidth(B_WIDTH_FROM_LABEL); 168 | 169 | fTabsVec.push_back(new ImageTab("home")); 170 | fTabView->AddTab(homeLayout->View(), fTabsVec.back()); 171 | fTabsVec.back()->SetLabel("Home"); 172 | fTabsVec.push_back(new ImageTab("zoom_fit_best")); 173 | fTabView->AddTab(viewLayout->View(), fTabsVec.back()); 174 | fTabsVec.back()->SetLabel("View"); 175 | fTabsVec.push_back(new ImageTab("marker")); 176 | fTabView->AddTab(editLayout->View(), fTabsVec.back()); 177 | fTabsVec.back()->SetLabel("Edit"); 178 | fTabsVec.push_back(new ImageTab("configure")); 179 | fTabView->AddTab(configureLayout->View(), fTabsVec.back()); 180 | fTabsVec.back()->SetLabel("Configure"); 181 | fTabsVec.push_back(new ImageTab("help")); 182 | fTabView->AddTab(helpLayout->View(), fTabsVec.back()); 183 | fTabsVec.back()->SetLabel("Help"); 184 | 185 | BLayoutBuilder::Group<>(this) 186 | .Add(fTabView) 187 | ; 188 | //fTabView->SetExplicitMaxSize(BSize(10000, 50)); 189 | // fTabView->SetExplicitMinSize(BSize(0, 50)); 190 | } 191 | 192 | 193 | void 194 | MainWindowRB::AttachedToWindow(void) 195 | { 196 | fPageNavigationView->SetTarget(this); 197 | //int size = fTabView->CountTabs(); 198 | 199 | // for (int i = 0; i < size; ++i) 200 | // fTabView->ViewForTab(i)->SetViewColor(220,220,255,255); 201 | BGroupView::AttachedToWindow(); 202 | 203 | } 204 | 205 | 206 | int32 207 | MainWindowRB::ActiveTab(void) 208 | { 209 | return fTabView->Selection(); 210 | } 211 | 212 | 213 | void 214 | MainWindowRB::SetActiveTab(int32 tab) 215 | { 216 | fTabView->Select(tab); 217 | } 218 | 219 | 220 | inline void 221 | MainWindowRB::_GoToPage(int pageNumber) 222 | { 223 | BMessage msg(MSG_GOTO_PAGE); 224 | msg.AddInt32("info", pageNumber); 225 | Window()->PostMessage(&msg); 226 | } 227 | 228 | 229 | void 230 | MainWindowRB::SetDocumentPages(int pages) 231 | { 232 | fPages = pages; 233 | fPageNavigationView->SetMaxValue(pages); 234 | } 235 | 236 | 237 | void 238 | MainWindowRB::MessageReceived(BMessage* message) 239 | { 240 | switch (message->what) { 241 | 242 | case MSG_ACTIVE_PAGE: 243 | case MSG_GOTO_PAGE: 244 | { 245 | int32 value; 246 | message->FindInt32("info", &value); 247 | ++value; 248 | fPageNavigationView->SetValue(value); 249 | 250 | break; 251 | } 252 | 253 | case M_PAGENUMBER: 254 | _GoToPage(fPageNavigationView->Value() - 1); 255 | break; 256 | 257 | default: 258 | BGroupView::MessageReceived(message); 259 | } 260 | } 261 | 262 | 263 | void 264 | MainWindowRB::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage) 265 | { 266 | switch (code) { 267 | case B_EXITED_VIEW: 268 | // fMainGroup->SetVisible(false); 269 | break; 270 | 271 | case B_ENTERED_VIEW: 272 | if (fAutohiding) { 273 | fMainGroup->SetVisible(true); 274 | MakeFocus(true); 275 | } 276 | break; 277 | 278 | default: 279 | break; 280 | } 281 | 282 | BGroupView::MouseMoved(where, code, dragMessage); 283 | } 284 | 285 | 286 | void 287 | MainWindowRB::MakeFocus(bool focusState) 288 | { 289 | if (fAutohiding) { 290 | if (focusState == false) 291 | fMainGroup->SetVisible(false); 292 | } 293 | 294 | BGroupView::MakeFocus(focusState); 295 | } 296 | 297 | 298 | void 299 | MainWindowRB::SetAutohiding(bool autohiding) 300 | { 301 | fAutohiding = autohiding; 302 | 303 | if (fAutohiding) 304 | fMainGroup->SetVisible(false); 305 | else 306 | fMainGroup->SetVisible(true); 307 | } 308 | -------------------------------------------------------------------------------- /application/MainWindowRB.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2011 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #ifndef MAINWINDOWRB_H 10 | #define MAINWINDOWRB_H 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #include "Debug.h" 19 | #include "ImageButton.h" 20 | #include "ImagePopUp.h" 21 | #include "ImageTabView.h" 22 | #include "PageNavigationView.h" 23 | 24 | class MainWindowRB : public BGroupView 25 | { 26 | public: 27 | MainWindowRB(void); 28 | virtual void MouseMoved(BPoint where, uint32 code, 29 | const BMessage* dragMessage); 30 | virtual void AttachedToWindow(void); 31 | virtual void MessageReceived(BMessage* message); 32 | virtual void MakeFocus(bool focusState = true); 33 | 34 | void SetDocumentPages(int pages); 35 | 36 | void SetActiveTab(int32 tab); 37 | int32 ActiveTab(void); 38 | 39 | void SetAutohiding(bool autohiding = true); 40 | bool IsAutohiding(void) { return fAutohiding; } 41 | 42 | enum{ M_PAGENUMBER = 'ip01' 43 | }; 44 | 45 | private: 46 | void _GoToPage(int pageNumber); 47 | 48 | ImageTabView* fTabView; 49 | std::vector fTabsVec; 50 | 51 | BGroupLayout* fMainGroup; 52 | PageNavigationView* fPageNavigationView; 53 | 54 | ImageButton* fOpenFileButton; 55 | ImageButton* fQuitButton; 56 | ImageButton* fSupportButton; 57 | 58 | int fPages; 59 | int fMaxHeight; 60 | 61 | bool fAutohiding; 62 | 63 | Debug out; 64 | }; 65 | 66 | #endif // MAINWINDOWRB_H 67 | -------------------------------------------------------------------------------- /application/Makefile: -------------------------------------------------------------------------------- 1 | ## Haiku Generic Makefile v2.6 ## 2 | 3 | ## Fill in this file to specify the project being created, and the referenced 4 | ## Makefile-Engine will do all of the hard work for you. This handles any 5 | ## architecture of Haiku. 6 | 7 | # The name of the binary. 8 | NAME = DocumentViewer 9 | 10 | # The type of binary, must be one of: 11 | # APP: Application 12 | # SHARED: Shared library or add-on 13 | # STATIC: Static library archive 14 | # DRIVER: Kernel driver 15 | TYPE = APP 16 | 17 | # If you plan to use localization, specify the application's MIME signature. 18 | APP_MIME_SIG = 19 | 20 | # The following lines tell Pe and Eddie where the SRCS, RDEFS, and RSRCS are 21 | # so that Pe and Eddie can fill them in for you. 22 | #%{ 23 | # @src->@ 24 | 25 | # Specify the source files to use. Full paths or paths relative to the 26 | # Makefile can be included. All files, regardless of directory, will have 27 | # their object files created in the common object directory. Note that this 28 | # means this Makefile will not work correctly if two source files with the 29 | # same name (source.c or source.cpp) are included from different directories. 30 | # Also note that spaces in folder names do not work well with this Makefile. 31 | SRCS = BaseEngine.cpp \ 32 | BookmarksView.cpp \ 33 | CircleMenuView.cpp \ 34 | DJVUEngine.cpp \ 35 | DocumentView.cpp \ 36 | ImageButton.cpp \ 37 | ImagePopUp.cpp \ 38 | ImageSpinner.cpp \ 39 | ImageTabView.cpp \ 40 | main.cpp \ 41 | MainWindow.cpp \ 42 | MainWindowRB.cpp \ 43 | NumberControl.cpp \ 44 | OutlineView.cpp \ 45 | PageNavigationView.cpp \ 46 | PasswordRequestWindow.cpp \ 47 | PDFEngine.cpp \ 48 | PDFFilter.cpp \ 49 | PreviewView.cpp \ 50 | PrintingWindow.cpp \ 51 | PrintPreviewView.cpp \ 52 | SearchView.cpp 53 | 54 | # Specify the resource definition files to use. Full or relative paths can be 55 | # used. 56 | RDEFS = DocumentViewer.rdef Icons.rdef 57 | 58 | # Specify the resource files to use. Full or relative paths can be used. 59 | # Both RDEFS and RSRCS can be utilized in the same Makefile. 60 | RSRCS = 61 | 62 | # End Pe/Eddie support. 63 | # @<-src@ 64 | #%} 65 | 66 | # Specify libraries to link against. 67 | # There are two acceptable forms of library specifications: 68 | # - if your library follows the naming pattern of libXXX.so or libXXX.a, 69 | # you can simply specify XXX for the library. (e.g. the entry for 70 | # "libtracker.so" would be "tracker") 71 | # 72 | # - for GCC-independent linking of standard C++ libraries, you can use 73 | # $(STDCPPLIBS) instead of the raw "stdc++[.r4] [supc++]" library names. 74 | # 75 | # - if your library does not follow the standard library naming scheme, 76 | # you need to specify the path to the library and it's name. 77 | # (e.g. for mylib.a, specify "mylib.a" or "path/mylib.a") 78 | LIBS = be $(STDCPPLIBS) columnlistview translation tracker \ 79 | z freetype jpeg mupdf djvulibre 80 | 81 | # Specify additional paths to directories following the standard libXXX.so 82 | # or libXXX.a naming scheme. You can specify full paths or paths relative 83 | # to the Makefile. The paths included are not parsed recursively, so 84 | # include all of the paths where libraries must be found. Directories where 85 | # source files were specified are automatically included. 86 | LIBPATHS = 87 | 88 | # Additional paths to look for system headers. These use the form 89 | # "#include
". Directories that contain the files in SRCS are 90 | # NOT auto-included here. 91 | SYSTEM_INCLUDE_PATHS = /system/develop/headers/private/interface/ 92 | 93 | # Additional paths paths to look for local headers. These use the form 94 | # #include "header". Directories that contain the files in SRCS are 95 | # automatically included. 96 | LOCAL_INCLUDE_PATHS = 97 | 98 | # Specify the level of optimization that you want. Specify either NONE (O0), 99 | # SOME (O1), FULL (O2), or leave blank (for the default optimization level). 100 | OPTIMIZE := SOME 101 | 102 | # Specify the codes for languages you are going to support in this 103 | # application. The default "en" one must be provided too. "make catkeys" 104 | # will recreate only the "locales/en.catkeys" file. Use it as a template 105 | # for creating catkeys for other languages. All localization files must be 106 | # placed in the "locales" subdirectory. 107 | LOCALES = 108 | 109 | # Specify all the preprocessor symbols to be defined. The symbols will not 110 | # have their values set automatically; you must supply the value (if any) to 111 | # use. For example, setting DEFINES to "DEBUG=1" will cause the compiler 112 | # option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG" would pass 113 | # "-DDEBUG" on the compiler's command line. 114 | DEFINES = 115 | 116 | # Specify the warning level. Either NONE (suppress all warnings), 117 | # ALL (enable all warnings), or leave blank (enable default warnings). 118 | WARNINGS = ALL 119 | 120 | # With image symbols, stack crawls in the debugger are meaningful. 121 | # If set to "TRUE", symbols will be created. 122 | SYMBOLS := 123 | 124 | # Includes debug information, which allows the binary to be debugged easily. 125 | # If set to "TRUE", debug info will be created. 126 | DEBUGGER := TRUE 127 | 128 | # Specify any additional compiler flags to be used. 129 | COMPILER_FLAGS = -std=c++11 130 | 131 | # Specify any additional linker flags to be used. 132 | LINKER_FLAGS = 133 | 134 | # Specify the version of this binary. Example: 135 | # -app 3 4 0 d 0 -short 340 -long "340 "`echo -n -e '\302\251'`"1999 GNU GPL" 136 | # This may also be specified in a resource. 137 | APP_VERSION := 138 | 139 | # (Only used when "TYPE" is "DRIVER"). Specify the desired driver install 140 | # location in the /dev hierarchy. Example: 141 | # DRIVER_PATH = video/usb 142 | # will instruct the "driverinstall" rule to place a symlink to your driver's 143 | # binary in ~/add-ons/kernel/drivers/dev/video/usb, so that your driver will 144 | # appear at /dev/video/usb when loaded. The default is "misc". 145 | DRIVER_PATH = 146 | 147 | ## Include the Makefile-Engine 148 | DEVEL_DIRECTORY := \ 149 | $(shell findpaths -r "makefile_engine" B_FIND_PATH_DEVELOP_DIRECTORY) 150 | include $(DEVEL_DIRECTORY)/etc/makefile-engine 151 | -------------------------------------------------------------------------------- /application/Messages.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2011 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #ifndef MESSAGES_H 10 | #define MESSAGES_H 11 | 12 | enum 13 | { 14 | MSG_ACTIVE_PAGE = 'ga01' , 15 | MSG_ANSWER_CURRENT_PAGENUMBER = 'ga02' , 16 | 17 | MSG_APP_QUIT = 'gb01' , 18 | 19 | MSG_FIT_PAGE_HEIGHT = 'gf01' , 20 | MSG_FIT_PAGE_WIDTH = 'gf02' , 21 | MSG_FULLSCREEN = 'gf03' , 22 | 23 | MSG_GOTO_PAGE = 'gg01' , 24 | 25 | MSG_HELP = 'gh01' , 26 | MSG_HIGHLIGHT_RECT = 'gh02' , 27 | 28 | MSG_NO_FIT = 'gn01' , 29 | MSG_NO_ZOOM = 'ge02' , 30 | 31 | 32 | MSG_OPEN_FILE = 'go01' , 33 | MSG_OPEN_FILE_PANEL = 'go02' , 34 | 35 | MSG_PRINT_DOCUMENT = 'gp01' , 36 | 37 | MSG_SEARCH_RESULT = 'gS01' , 38 | MSG_SETUP_PRINTER = 'gS02' , 39 | MSG_SUPPORT = 'gS03' , 40 | 41 | MSG_TELL_CURRENT_PAGENUMBER = 'gt01' , 42 | 43 | // View-Menu 44 | MSG_VIEW_ALWAYSONTOP = 'gv01' , 45 | MSG_ZOOM_IN = 'gz01' , 46 | 47 | MSG_ZOOM_OUT = 'gz03' 48 | }; 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /application/NumberControl.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2012 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #include "NumberControl.h" 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | 18 | NumberControl::NumberControl(unique_ptr message) 19 | : 20 | BTextView("number_control"), 21 | BInvoker(message.release(), NULL, NULL) 22 | { 23 | BFont font; 24 | font.SetSize(16); 25 | font.SetFlags(Flags() | B_FORCE_ANTIALIASING); 26 | font.SetFace(B_CONDENSED_FACE | B_BOLD_FACE); 27 | rgb_color color = make_color(0, 0, 0, 255); 28 | 29 | SetFontAndColor(&font, B_FONT_ALL, &color); 30 | 31 | SetAlignment(B_ALIGN_HORIZONTAL_CENTER); 32 | //TODO: 33 | //SetWordWrap(false); 34 | 35 | font_height fontHeight; 36 | GetFontHeight(&fontHeight); 37 | auto height = fontHeight.ascent + fontHeight.descent + fontHeight.leading; 38 | height *= 1.35; 39 | SetExplicitMinSize(BSize(StringWidth("999999"), height)); 40 | SetExplicitMaxSize(BSize(StringWidth("999999"), height)); 41 | } 42 | 43 | 44 | void 45 | NumberControl::KeyDown(const char* bytes, int32 numBytes) 46 | { 47 | if (numBytes == 1) { 48 | auto value = bytes[0]; 49 | switch (value) { 50 | case B_ENTER: 51 | SetValue(atoi(Text())); 52 | Invoke(); 53 | MakeFocus(false); 54 | break; 55 | 56 | case B_DELETE: 57 | case B_INSERT: 58 | case B_BACKSPACE: 59 | BTextView::KeyDown(bytes, numBytes); 60 | break; 61 | 62 | default: 63 | if (value >= '0' && value <= '9' && TextLength() < 4) 64 | BTextView::KeyDown(bytes, numBytes); 65 | 66 | break; 67 | } 68 | } 69 | } 70 | 71 | 72 | float 73 | NumberControl::Value(void) 74 | { 75 | return fValue; 76 | } 77 | 78 | 79 | void 80 | NumberControl::SetValue(float const& value) 81 | { 82 | fValue = value; 83 | BString str; 84 | str << static_cast(fValue); 85 | SetText(str); 86 | } 87 | -------------------------------------------------------------------------------- /application/NumberControl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2012 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #ifndef NUMBERCONTROL_H 10 | #define NUMBERCONTROL_H 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #include "Debug.h" 19 | 20 | class NumberControl : public BTextView, public BInvoker 21 | { 22 | public: 23 | NumberControl(std::unique_ptr message); 24 | 25 | virtual void KeyDown(const char* bytes, int32 numBytes); 26 | void SetValue(float const& value); 27 | float Value(void); 28 | private: 29 | 30 | float fValue; 31 | Debug out; 32 | 33 | }; 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /application/OutlineView.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2011 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #include "OutlineView.h" 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include "ImageButton.h" 16 | #include "MainWindow.h" 17 | #include "Messages.h" 18 | 19 | using namespace std; 20 | 21 | 22 | EditListItemWindow::EditListItemWindow(OutlineItem* item, const BString& name) 23 | : 24 | BWindow(BRect(0, 0, 300, 100), name, B_MODAL_WINDOW_LOOK, 25 | B_FLOATING_ALL_WINDOW_FEEL, B_ASYNCHRONOUS_CONTROLS 26 | | B_AUTO_UPDATE_SIZE_LIMITS | B_NOT_MINIMIZABLE | B_NOT_ZOOMABLE 27 | | B_NOT_CLOSABLE 28 | /*| B_OUTLINE_RESIZE*/ 29 | /* | B_WILL_ACCEPT_FIRST_CLICK*/), 30 | fCode(0) 31 | { 32 | fNameTC = new BTextControl("Name ", "", nullptr); 33 | fNameTC->SetText(item->Name()); 34 | fPageTC = new BTextControl("Page ", "", nullptr); 35 | BString str; 36 | str << item->PageNumber() + 1; 37 | 38 | fPageTC->SetText(str); 39 | 40 | BButton* okButton = new BButton("ok_button", "OK", new BMessage(M_OK)); 41 | SetDefaultButton(okButton); 42 | 43 | fGoToPageCB = new BCheckBox("Go to page "); 44 | fGoToPageCB->SetValue(1); 45 | 46 | BGroupLayout* layout; 47 | layout = BLayoutBuilder::Group<>(B_VERTICAL, 0) 48 | .SetInsets(5, 5, 5, 5) 49 | .Add(fGoToPageCB) 50 | ; 51 | 52 | BBox* box1 = new BBox("box1"); 53 | box1->SetBorder(B_FANCY_BORDER); 54 | box1->AddChild(layout->View()); 55 | 56 | 57 | BLayoutBuilder::Group<>(this, B_VERTICAL, 10) 58 | .SetInsets(10, 10, 10, 10) 59 | .Add(fNameTC) 60 | .Add(fPageTC) 61 | //.Add(box1) 62 | .AddGlue(0) 63 | .AddGroup(B_HORIZONTAL, 0) 64 | .AddGlue(0) 65 | .Add(okButton) 66 | .End() 67 | .End(); 68 | 69 | fNameTC->MakeFocus(); 70 | fItem = item; 71 | } 72 | 73 | 74 | void 75 | EditListItemWindow::SetResponse(const int& code, BLooper* looper, BHandler* handler) 76 | { 77 | fTargetLooper = looper; 78 | fTargetHandler = handler; 79 | fCode = code; 80 | } 81 | 82 | 83 | void 84 | EditListItemWindow::MessageReceived(BMessage* message) 85 | { 86 | switch (message->what) { 87 | case M_OK: 88 | { 89 | fItem->SetName(fNameTC->Text()); 90 | fItem->SetPageNumber(atoi(fPageTC->Text()) - 1); 91 | fTargetLooper->PostMessage(fCode, fTargetHandler); 92 | Close(); 93 | 94 | break; 95 | } 96 | 97 | 98 | default: 99 | BWindow::MessageReceived(message); 100 | break; 101 | } 102 | } 103 | 104 | 105 | OutlineItem::OutlineItem(const BString& name, const int& pageNumber, 106 | uint32 outlineLevel, bool expanded) 107 | : 108 | BListItem(), 109 | fName(name), 110 | fPageNumber(pageNumber) 111 | { 112 | } 113 | 114 | 115 | OutlineItem::~OutlineItem() 116 | { 117 | } 118 | 119 | 120 | void 121 | OutlineItem::SetName(const BString& name) 122 | { 123 | fName = name; 124 | } 125 | 126 | 127 | void 128 | OutlineItem::DrawItem(BView *owner, BRect itemRect, bool complete) 129 | { 130 | rgb_color kBlack = {0, 0, 0, 0}; 131 | rgb_color kHighlight = {156, 154, 156, 0}; 132 | 133 | if (IsSelected() || complete) { 134 | rgb_color color; 135 | if (IsSelected()) 136 | color = kHighlight; 137 | else 138 | color = owner->ViewColor(); 139 | 140 | owner->SetHighColor(color); 141 | owner->SetLowColor(color); 142 | owner->FillRect(itemRect); 143 | owner->SetHighColor(kBlack); 144 | 145 | } else { 146 | owner->SetLowColor(owner->ViewColor()); 147 | } 148 | 149 | BFont font = be_plain_font; 150 | font_height finfo; 151 | font.GetHeight(&finfo); 152 | 153 | BPoint point = BPoint(itemRect.left + 5, itemRect.bottom - finfo.descent + 1); 154 | 155 | owner->SetHighColor(kBlack); 156 | owner->SetFont(be_plain_font); 157 | owner->MovePenTo(point); 158 | 159 | owner->MovePenTo(point); 160 | owner->DrawString(fName); 161 | } 162 | 163 | 164 | OutlineListView::OutlineListView(void) 165 | : 166 | BOutlineListView("outline_list_view"), 167 | fStartSearchIndex(0) 168 | { 169 | 170 | } 171 | 172 | 173 | void 174 | OutlineListView::ReverseOrder(OutlineItem* super) 175 | { 176 | if (super == nullptr) 177 | return; 178 | 179 | int32 end = CountItemsUnder(super, true) - 1; 180 | if (end < 1) 181 | return; 182 | 183 | for (int start = 0; start < end; ++start, --end) 184 | SwapItems(FullListIndexOf(ItemUnderAt(super, true, start)), 185 | FullListIndexOf(ItemUnderAt(super, true, end))); 186 | } 187 | 188 | 189 | void 190 | OutlineListView::MoveFirstToEnd(OutlineItem* super) 191 | { 192 | // move the element fromt the front to the end of the list 193 | int32 transpositions = CountItemsUnder(super, true) - 1; 194 | for (int i = 0; i < transpositions; ++i) 195 | SwapItems(FullListIndexOf(ItemUnderAt(super, true, i)), 196 | FullListIndexOf(ItemUnderAt(super, true, i + 1))); 197 | } 198 | 199 | void 200 | OutlineListView::MouseDown(BPoint where) 201 | { 202 | int32 idx = CurrentSelection(); 203 | BOutlineListView::MouseDown(where); 204 | 205 | if (CurrentSelection() == idx) { 206 | DeselectAll(); 207 | } 208 | } 209 | 210 | 211 | void 212 | OutlineListView::SetEngine(BaseEngine* engine) 213 | { 214 | if (engine == nullptr) 215 | return; 216 | 217 | MakeEmpty(); 218 | fEngine = engine; 219 | fEngine->WriteOutline(this); 220 | ReverseOrder(); 221 | } 222 | 223 | 224 | void 225 | OutlineListView::ReverseOrder(void) 226 | { 227 | int32 size = FullListCountItems(); 228 | 229 | for (int i = 0; i < size; ++i) 230 | ReverseOrder(static_cast(FullListItemAt(i))); 231 | } 232 | 233 | 234 | void 235 | OutlineListView::Find(const BString& name) 236 | { 237 | if (name.Length() == 0) 238 | return; 239 | 240 | if (name != fSearchString) { 241 | fStartSearchIndex = 0; 242 | fSearchString = name; 243 | } 244 | 245 | int32 size = FullListCountItems(); 246 | OutlineItem* item; 247 | 248 | for (int j = 0; j < 2; ++j) { 249 | for (int i = fStartSearchIndex; i < size; ++i) { 250 | item = static_cast(FullListItemAt(i)); 251 | if (item->Name().IFindFirst(name) != B_ERROR) { 252 | DeselectAll(); 253 | Select(i, true); 254 | ScrollToSelection(); 255 | fStartSearchIndex = (i + 1) % size; 256 | return; 257 | } 258 | } 259 | fStartSearchIndex = 0; 260 | } 261 | } 262 | 263 | 264 | OutlineItem* 265 | OutlineListView::_SelectedItem(void) 266 | { 267 | return static_cast< OutlineItem* >(FullListItemAt(CurrentSelection())); 268 | } 269 | 270 | 271 | inline void 272 | OutlineListView::_GoToPage(const int& pageNumber) 273 | { 274 | BMessage msg(MSG_GOTO_PAGE); 275 | msg.AddInt32("info", pageNumber); 276 | Window()->PostMessage(&msg); 277 | } 278 | 279 | 280 | status_t 281 | OutlineListView::Invoke(BMessage* message) 282 | { 283 | auto item = _SelectedItem(); 284 | if (item) 285 | _GoToPage(item->PageNumber()); 286 | 287 | BListView::Invoke(message); 288 | 289 | // added this return call to silence -Wreturn-type warning 290 | // should probably be replaced by real error handling 291 | return B_OK; 292 | } 293 | 294 | 295 | void 296 | OutlineListView::RemoveCurrentSelection(void) 297 | { 298 | int32 idx = FullListCurrentSelection(); 299 | RemoveItem(idx); 300 | Select(idx - 1); 301 | } 302 | 303 | 304 | bool 305 | OutlineListView::InitiateDrag(BPoint point, int32 itemIndex, bool initialySelected) 306 | { 307 | !out << "DRAG" << endl; 308 | return BOutlineListView::InitiateDrag(point, itemIndex, initialySelected); 309 | } 310 | 311 | 312 | 313 | OutlineView::OutlineView(void) 314 | : 315 | BGroupView("outline", B_VERTICAL, 0) 316 | { 317 | const float iconHeight = 30; 318 | fDeleteItem = new ImageButton("quit", 319 | new BMessage(M_DELETE_ITEM), 0.3, 1, "Remove outline"); 320 | fDeleteItem->SetExplicitMinSize(BSize(iconHeight, iconHeight)); 321 | fDeleteItem->SetExplicitMaxSize(BSize(iconHeight, iconHeight)); 322 | 323 | fAddItem = new ImageButton("plus", 324 | new BMessage(M_ADD_ITEM), 0.3, 1, "Add outline"); 325 | fAddItem->SetExplicitMinSize(BSize(iconHeight, iconHeight)); 326 | fAddItem->SetExplicitMaxSize(BSize(iconHeight, iconHeight)); 327 | 328 | fEditItem = new ImageButton("edit", 329 | new BMessage(M_EDIT_ITEM), 0.3, 1, "Edit outline"); 330 | fEditItem->SetExplicitMinSize(BSize(iconHeight, iconHeight)); 331 | fEditItem->SetExplicitMaxSize(BSize(iconHeight, iconHeight)); 332 | 333 | fFindNext = new ImageButton("find_next", 334 | new BMessage(M_FIND_NEXT), 0.3, 1, "Search outline"); 335 | fFindNext->SetExplicitMinSize(BSize(iconHeight, iconHeight)); 336 | fFindNext->SetExplicitMaxSize(BSize(iconHeight, iconHeight)); 337 | 338 | fOutlineListView = new OutlineListView(); 339 | 340 | fVScrollBar = new BScrollBar("v_scrollbar", 341 | fOutlineListView, 0, 100, B_VERTICAL); 342 | fHScrollBar = new BScrollBar("h_scrollbar", 343 | fOutlineListView, 0, 100, B_HORIZONTAL); 344 | 345 | fSearchTC = new BTextControl("", "", new BMessage(M_FIND_NEXT)); 346 | 347 | BGroupLayout* 348 | controlsLayout = BLayoutBuilder::Group<>(B_VERTICAL, 0) 349 | .AddGroup(B_HORIZONTAL, 0) 350 | .Add(fAddItem) 351 | .Add(fEditItem) 352 | .Add(fDeleteItem) 353 | .Add(fSearchTC) 354 | .Add(fFindNext) 355 | .End() 356 | ; 357 | 358 | BBox* box1 = new BBox("box1"); 359 | box1->SetBorder(B_FANCY_BORDER); 360 | box1->AddChild(controlsLayout->View()); 361 | 362 | BGroupLayout* 363 | listLayout = BLayoutBuilder::Group<>(B_HORIZONTAL, 0) 364 | .Add(fOutlineListView) 365 | .Add(fVScrollBar) 366 | ; 367 | 368 | BBox* box2 = new BBox("box2"); 369 | box2->SetBorder(B_FANCY_BORDER); 370 | box2->AddChild(listLayout->View()); 371 | 372 | BLayoutBuilder::Group<>(this) 373 | .Add(box1) 374 | .Add(box2) 375 | .End() 376 | ; 377 | } 378 | 379 | 380 | void 381 | OutlineView::AttachedToWindow(void) 382 | { 383 | fDeleteItem->SetTarget(this); 384 | fAddItem->SetTarget(this); 385 | fEditItem->SetTarget(this); 386 | fSearchTC->SetTarget(this); 387 | fFindNext->SetTarget(this); 388 | BGroupView::AttachedToWindow(); 389 | } 390 | 391 | 392 | void 393 | OutlineView::EngineChanged(BaseEngine* engine) 394 | { 395 | //ToDo: save outline 396 | fOutlineListView->SetEngine(engine); 397 | Invalidate(); 398 | } 399 | 400 | 401 | void 402 | OutlineView::_ShowEditWindow(void) 403 | { 404 | int idx = fOutlineListView->CurrentSelection(); 405 | if (idx < 0) 406 | return; 407 | 408 | OutlineItem* item = static_cast(fOutlineListView->FullListItemAt(idx)); 409 | item->SetPageNumber(_CurrentPageNumber()); 410 | auto temp = new EditListItemWindow(item); 411 | temp->SetResponse(M_ITEM_CHANGED, Window(), this); 412 | temp->CenterIn(Window()->Frame()); 413 | temp->Show(); 414 | } 415 | 416 | 417 | int 418 | OutlineView::_CurrentPageNumber(void) 419 | { 420 | return static_cast(Window())->CurrentPageNumber(); 421 | } 422 | 423 | 424 | void 425 | OutlineView::MessageReceived(BMessage* message) 426 | { 427 | switch (message->what) { 428 | case M_DELETE_ITEM: 429 | fOutlineListView->RemoveCurrentSelection(); 430 | break; 431 | 432 | case M_ADD_ITEM: 433 | { 434 | OutlineItem* item = new OutlineItem("", _CurrentPageNumber()); 435 | OutlineItem* super = nullptr; 436 | int idx = fOutlineListView->CurrentSelection(); 437 | if (idx < 0) { 438 | fOutlineListView->AddItem(item); 439 | } else { 440 | super = static_cast(fOutlineListView->FullListItemAt(idx)); 441 | fOutlineListView->AddUnder(item, super); 442 | } 443 | 444 | fOutlineListView->MoveFirstToEnd(super); 445 | 446 | fOutlineListView->Select(fOutlineListView->IndexOf(item)); 447 | fOutlineListView->Invalidate(); 448 | 449 | _ShowEditWindow(); 450 | 451 | break; 452 | } 453 | 454 | case M_EDIT_ITEM: 455 | _ShowEditWindow(); 456 | break; 457 | 458 | case M_ITEM_CHANGED: 459 | { 460 | fOutlineListView->Invalidate(); 461 | /* 462 | auto compare = [](const OutlineItem* i1, const OutlineItem* i2){ 463 | return i1->PageNumber() - i2->PageNumber(); 464 | }; 465 | 466 | fOutlineListView->FullListSortItems(compare); 467 | */ 468 | break; 469 | } 470 | 471 | case M_FIND_NEXT: 472 | fOutlineListView->Find(fSearchTC->Text()); 473 | break; 474 | 475 | default: 476 | BGroupView::MessageReceived(message); 477 | break; 478 | } 479 | } 480 | -------------------------------------------------------------------------------- /application/OutlineView.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright 2011-2011 Haiku Inc. All rights reserved. 4 | * Distributed under the terms of the MIT License. 5 | * 6 | * Authors: 7 | * Ciprian Nedisan (cipri) 8 | * 9 | */ 10 | #ifndef OUTLINEVIEW_H 11 | #define OUTLINEVIEW_H 12 | 13 | #include 14 | #include 15 | 16 | 17 | extern "C" { 18 | #include 19 | } 20 | 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "BaseEngine.h" 32 | #include "Debug.h" 33 | #include "ImageButton.h" 34 | 35 | 36 | class OutlineItem : public BListItem 37 | { 38 | public: 39 | OutlineItem(const BString& name, const int& pageNumber = 0, 40 | uint32 outlineLevel = 0, bool expanded = true); 41 | ~OutlineItem(); 42 | virtual void DrawItem(BView* owner, BRect itemRect, bool = false); 43 | 44 | void SetName(const BString& name); 45 | BString Name(void) { return fName; } 46 | 47 | const int& PageNumber(void) const 48 | { 49 | return fPageNumber; 50 | } 51 | 52 | void SetPageNumber(const int& pageNumber) 53 | { 54 | fPageNumber = pageNumber; 55 | } 56 | 57 | private: 58 | BString fName; 59 | int fPageNumber; 60 | }; 61 | 62 | 63 | class OutlineListView : public BOutlineListView 64 | { 65 | public: 66 | OutlineListView(void); 67 | virtual status_t Invoke(BMessage* message = nullptr); 68 | virtual void MouseDown(BPoint where); 69 | virtual bool InitiateDrag(BPoint point, int32 itemIndex, 70 | bool initialySelected); 71 | 72 | void RemoveCurrentSelection(void); 73 | void SetEngine(BaseEngine* engine); 74 | void ReverseOrder(OutlineItem* super); 75 | void ReverseOrder(void); 76 | void MoveFirstToEnd(OutlineItem* super); 77 | void Find(const BString& name); 78 | 79 | private: 80 | OutlineItem* _SelectedItem(void); 81 | inline void _GoToPage(const int& pageNumber); 82 | 83 | BaseEngine* fEngine; 84 | 85 | BString fSearchString; 86 | int32 fStartSearchIndex; 87 | 88 | Debug out; 89 | 90 | }; 91 | 92 | 93 | class EditListItemWindow : public BWindow 94 | { 95 | public: 96 | EditListItemWindow(OutlineItem* item, const BString& name = "Edit"); 97 | 98 | virtual void MessageReceived(BMessage* message); 99 | 100 | void SetResponse(const int& code, BLooper* looper, BHandler* handler = nullptr); 101 | 102 | enum{ M_OK = 'io01' 103 | 104 | }; 105 | 106 | private: 107 | BTextControl* fNameTC; 108 | BTextControl* fPageTC; 109 | BCheckBox* fGoToPageCB; 110 | OutlineItem * fItem; 111 | BLooper* fTargetLooper; 112 | BHandler* fTargetHandler; 113 | int fCode; 114 | 115 | Debug out; 116 | 117 | }; 118 | 119 | 120 | class OutlineView : public BGroupView 121 | { 122 | public: 123 | OutlineView(void); 124 | virtual void MessageReceived(BMessage* message); 125 | virtual void AttachedToWindow(void); 126 | 127 | virtual void EngineChanged(BaseEngine* engine); 128 | 129 | 130 | enum{ M_ADD_ITEM = 'ic01', M_DELETE_ITEM = 'id01', 131 | M_EDIT_ITEM = 'ie01', M_FIND_NEXT = 'if01', 132 | M_ITEM_CHANGED = 'ii01' 133 | }; 134 | 135 | private: 136 | int _CurrentPageNumber(void); 137 | void _ShowEditWindow(void); 138 | 139 | BScrollBar* fVScrollBar; 140 | BScrollBar* fHScrollBar; 141 | 142 | BTextControl* fSearchTC; 143 | 144 | ImageButton* fEditItem; 145 | ImageButton* fDeleteItem; 146 | ImageButton* fAddItem; 147 | ImageButton* fFindNext; 148 | 149 | OutlineListView* fOutlineListView; 150 | Debug out; 151 | }; 152 | 153 | #endif 154 | -------------------------------------------------------------------------------- /application/PDFEngine.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2012 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #include "PDFEngine.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "Flags.h" 17 | #include "Messages.h" 18 | #include "OutlineView.h" 19 | #include "PasswordRequestWindow.h" 20 | 21 | using namespace std; 22 | 23 | 24 | struct fz_lock_impl { 25 | fz_locks_context context; 26 | 27 | fz_lock_impl() { 28 | for (int i = 0; i < FZ_LOCK_MAX; i++) 29 | locks[i] = PTHREAD_MUTEX_INITIALIZER; 30 | 31 | context.user = this; 32 | context.lock = lock; 33 | context.unlock = unlock; 34 | } 35 | 36 | static void lock(void* user, int lock) { 37 | pthread_mutex_lock(&((fz_lock_impl*)user)->locks[lock]); 38 | } 39 | static void unlock(void* user, int lock) { 40 | pthread_mutex_unlock(&((fz_lock_impl*)user)->locks[lock]); 41 | } 42 | 43 | private: 44 | pthread_mutex_t locks[FZ_LOCK_MAX]; 45 | }; 46 | 47 | 48 | PDFEngine::PDFEngine(BString fileName, BString& password) 49 | : 50 | fFileName(fileName), 51 | fPassword(password) 52 | { 53 | fHighlightUnderText = true; 54 | fDocument = nullptr; 55 | fz_var(fDocument); 56 | 57 | fz_lock_impl* locks = new fz_lock_impl; 58 | fContext = fz_new_context(nullptr, &locks->context, FZ_STORE_DEFAULT); 59 | fz_register_document_handlers(fContext); 60 | // why bgr instead of rgb? 61 | fColorSpace = fz_device_bgr(fContext); 62 | 63 | if (!fContext) { 64 | !out << "cannot init context" << endl; 65 | exit(1); 66 | } 67 | 68 | fz_try(fContext) { 69 | fDocument = fz_open_document(fContext, fileName.String()); 70 | } fz_catch(fContext) { 71 | !out << "can not open document" << endl; 72 | throw; 73 | } 74 | 75 | if (fz_needs_password(fContext, fDocument)) { 76 | if (password.Length() == 0) { 77 | while (true) { 78 | auto t = (new PasswordRequestWindow())->Go(); 79 | if (std::get<1>(t) == false) 80 | throw "wrong password"; 81 | 82 | if (fz_authenticate_password(fContext, fDocument, std::get<0>(t))) { 83 | password = std::get<0>(t); 84 | break; 85 | } 86 | } 87 | } else { 88 | int okay = fz_authenticate_password(fContext, fDocument, 89 | const_cast(password.String())); 90 | 91 | if (!okay) 92 | throw "wrong password"; 93 | } 94 | } 95 | 96 | // Contexts for alternate threads 97 | fRenderContext = fz_clone_context(fContext); 98 | 99 | Start(); 100 | } 101 | 102 | 103 | PDFEngine::~PDFEngine() 104 | { 105 | Stop(); 106 | 107 | if (fDocument) { 108 | fz_drop_document(fContext, fDocument); 109 | } 110 | 111 | if (fContext) { 112 | fz_lock_impl* locks = static_cast(fContext->locks.user); 113 | fz_drop_context(fContext); 114 | delete locks; 115 | } 116 | } 117 | 118 | 119 | int 120 | PDFEngine::PageCount(void) const 121 | { 122 | int count = fz_count_pages(fContext, fDocument); 123 | return count; 124 | } 125 | 126 | 127 | 128 | void 129 | PDFEngine::WriteOutline(BOutlineListView* list) 130 | { 131 | auto outline = fz_load_outline(fContext, fDocument); 132 | 133 | std::function OutlineToList = 134 | [&OutlineToList](fz_context* ctx, fz_document* doc, fz_outline* outline, BOutlineListView* list, BListItem* super, int level) { 135 | OutlineItem* item; 136 | int page_number; 137 | while (outline) { 138 | page_number = fz_page_number_from_location(ctx, doc, outline->page); 139 | if (page_number > -1) 140 | item = new OutlineItem(outline->title, page_number); 141 | else 142 | item = new OutlineItem(outline->title, 0); 143 | 144 | list->AddUnder(item, super); 145 | 146 | if (outline->down) 147 | OutlineToList(ctx, doc, outline->down,list, item, level + 1); 148 | 149 | outline = outline->next; 150 | } 151 | }; 152 | 153 | OutlineToList(fContext, fDocument, outline, list, nullptr, 0); 154 | fz_drop_outline(fContext, outline); 155 | } 156 | 157 | 158 | namespace std { 159 | // FIXME remove when the compiler supports this C++11 feature. 160 | template 161 | std::unique_ptr make_unique(Args&&... args) 162 | { 163 | return std::unique_ptr(new T(std::forward(args)...)); 164 | } 165 | } 166 | 167 | 168 | std::tuple< std::vector, std::vector > 169 | PDFEngine::_FindString(BString const& name, int const& pageNumber) 170 | { 171 | vector contextVec; 172 | vector rectVec; 173 | 174 | bool needWholeWord = false; 175 | if (GHasFlag(fSearchFlag, SEARCH_WHOLE_WORD)) 176 | needWholeWord = true; 177 | 178 | bool needMatchCase = false; 179 | if (GHasFlag(fSearchFlag, SEARCH_MATCH_CASE)) 180 | needMatchCase = true; 181 | 182 | fz_page* page = nullptr; 183 | page = fz_load_page(fContext, fDocument, pageNumber); 184 | 185 | fz_device* dev = nullptr; 186 | fz_var(dev); 187 | 188 | fz_stext_page* text = nullptr; 189 | fz_var(text); 190 | 191 | fz_try(fContext) { 192 | text = fz_new_stext_page_from_page(fContext, page, NULL); 193 | dev = fz_new_stext_device(fContext, text, 0); 194 | 195 | // Load the text from the page 196 | fz_run_page(fContext, page, dev, fz_identity, NULL); 197 | fz_close_device(fContext, dev); 198 | fz_drop_device(fContext, dev); 199 | dev = nullptr; 200 | 201 | // Now actually get the boxes 202 | static const int MAX_SEARCHES = 500; 203 | fz_quad boxes[MAX_SEARCHES]; 204 | // Keep track of the hit marks 205 | int hit_marks[MAX_SEARCHES]; 206 | int count = fz_search_stext_page(fContext, text, name, hit_marks, boxes, MAX_SEARCHES); 207 | 208 | for (int i = 0; i < count; i++) { 209 | // Attempt to avoid duplicates 210 | if (hit_marks[i]) { 211 | fz_rect fr = fz_rect_from_quad(boxes[i]); 212 | BRect br; 213 | br.top = fr.y0; 214 | br.bottom = fr.y1; 215 | br.left = fr.x0; 216 | br.right = fr.x1; 217 | 218 | // Get some context: extract some text around the match by enlarging 219 | // the rect to cover a greater part of the text 220 | fr.x0 -= 1000; 221 | fr.x1 += 1000; 222 | 223 | BString context(fz_copy_rectangle(fContext, text, fr, false)); 224 | int pos = context.FindFirst(name); 225 | 226 | // Check that we get a case match if requested 227 | if (needMatchCase && pos < 0) 228 | continue; 229 | 230 | // Filter out non-whole word results 231 | if (needWholeWord) { 232 | if (pos > 0 && isalpha(context[pos - 1])) 233 | continue; 234 | if (isalpha(context[pos + name.Length()])) 235 | continue; 236 | } 237 | 238 | rectVec.push_back(br); 239 | contextVec.push_back(context); 240 | } 241 | } 242 | 243 | 244 | } fz_catch(fContext) { 245 | fz_close_device(fContext, dev); 246 | fz_drop_device(fContext, dev); 247 | fz_drop_stext_page(fContext, text); 248 | fz_rethrow(fContext); 249 | } 250 | 251 | return make_tuple(contextVec, rectVec); 252 | } 253 | 254 | 255 | BString 256 | PDFEngine::GetProperty(BString name) 257 | { 258 | BString property; 259 | 260 | return property; 261 | } 262 | 263 | 264 | BString 265 | PDFEngine::FileName(void) const 266 | { 267 | return fFileName; 268 | } 269 | 270 | 271 | unique_ptr 272 | PDFEngine::RenderBitmap(int const& pageNumber, 273 | uint32 const& width, uint32 const& height, int const& rotation) 274 | { 275 | if (pageNumber < 0 || pageNumber >= fPages) { 276 | return unique_ptr(nullptr); 277 | } 278 | 279 | fz_page *page; 280 | fz_display_list *list = nullptr; 281 | fz_device *dev = nullptr; 282 | 283 | fz_var(list); 284 | fz_var(dev); 285 | 286 | pthread_mutex_lock(&fRendermutex); 287 | 288 | bool stop = false; // variable for avoiding return in fz_catch 289 | fz_try(fRenderContext) { 290 | page = fz_load_page(fRenderContext, fDocument, pageNumber); 291 | } fz_catch(fRenderContext) { 292 | pthread_mutex_unlock(&fRendermutex); 293 | stop = true; 294 | } 295 | 296 | if (stop) 297 | return std::make_unique(BRect(0, 0, width, height), B_RGBA32); 298 | 299 | fz_try(fRenderContext) { 300 | list = fz_new_display_list(fRenderContext, fz_empty_rect); 301 | dev = fz_new_list_device(fRenderContext, list); 302 | fz_run_page(fRenderContext, page, dev, fz_identity, nullptr); 303 | } fz_catch(fRenderContext) { 304 | fz_close_device(fRenderContext, dev); 305 | fz_drop_device(fRenderContext, dev); 306 | fz_drop_display_list(fRenderContext, list); 307 | fz_drop_page(fRenderContext, page); 308 | pthread_mutex_unlock(&fRendermutex); 309 | stop = true; 310 | } 311 | 312 | if (stop) 313 | return std::make_unique(BRect(0, 0, width, height), B_RGBA32); 314 | 315 | fz_close_device(fRenderContext, dev); 316 | fz_drop_device(fRenderContext, dev); 317 | dev = nullptr; 318 | 319 | fz_pixmap* image = nullptr; 320 | fz_var(image); 321 | 322 | fz_rect bounds = fz_bound_page(fRenderContext, page); 323 | 324 | float zoomFactor = 1; 325 | 326 | if (width <= 0) { 327 | zoomFactor = height / (bounds.y1 - bounds.y0); 328 | } else { 329 | zoomFactor = width / (bounds.x1 - bounds.x0); 330 | } 331 | 332 | fz_matrix ctm = fz_pre_scale(fz_rotate(fRotation), zoomFactor, zoomFactor); 333 | fz_irect pageBox = fz_round_rect(fz_transform_rect(bounds, ctm)); 334 | fz_separations *seps = fz_page_separations(fContext, page); 335 | 336 | fz_try(fRenderContext) { 337 | image = fz_new_pixmap_with_bbox(fRenderContext, fColorSpace, pageBox, seps, 1); 338 | 339 | fz_clear_pixmap_with_value(fRenderContext, image, 255); 340 | dev = fz_new_draw_device(fRenderContext, fz_identity, image); 341 | if (list) 342 | fz_run_display_list(fRenderContext, list, dev, ctm, bounds, nullptr); 343 | else 344 | fz_run_page(fRenderContext, page, dev, ctm, nullptr); 345 | 346 | fz_close_device(fRenderContext, dev); 347 | fz_drop_device(fRenderContext, dev); 348 | dev = nullptr; 349 | } fz_catch(fRenderContext) { 350 | fz_close_device(fRenderContext, dev); 351 | fz_drop_device(fRenderContext, dev); 352 | fz_drop_pixmap(fRenderContext, image); 353 | fz_drop_display_list(fRenderContext, list); 354 | fz_drop_page(fRenderContext, page); 355 | pthread_mutex_unlock(&fRendermutex); 356 | stop = true; 357 | } 358 | 359 | if (stop) 360 | return std::make_unique(BRect(0, 0, width, height), B_RGBA32); 361 | 362 | fz_flush_warnings(fRenderContext); 363 | 364 | int imageWidth = pageBox.x1 - pageBox.x0; 365 | int imageHeight = pageBox.y1 - pageBox.y0; 366 | 367 | 368 | BBitmap* bitmap = new BBitmap(BRect(0, 0, imageWidth - 1, imageHeight - 1), B_RGBA32); 369 | bitmap->SetBits(fz_pixmap_samples(fRenderContext, image), 370 | imageWidth * imageHeight * fz_pixmap_components(fRenderContext, image), 0, B_RGBA32); 371 | 372 | fz_close_device(fRenderContext, dev); 373 | fz_drop_device(fRenderContext, dev); 374 | fz_drop_pixmap(fRenderContext, image); 375 | fz_drop_display_list(fRenderContext, list); 376 | fz_drop_page(fRenderContext, page); 377 | 378 | pthread_mutex_unlock(&fRendermutex); 379 | return unique_ptr(bitmap); 380 | } 381 | 382 | 383 | std::pair 384 | PDFEngine::_RenderBitmap(int const& pageNumber) 385 | { 386 | unique_ptr bitmap = RenderBitmap(pageNumber, fDefaultRect.Width(), 387 | fDefaultRect.Height(), 0); 388 | 389 | return std::pair(bitmap.release(), false); 390 | } 391 | -------------------------------------------------------------------------------- /application/PDFEngine.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2012 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #ifndef PDFENGINE_H 10 | #define PDFENGINE_H 11 | 12 | extern "C" { 13 | #include 14 | //#include 15 | } 16 | 17 | 18 | #include 19 | 20 | #include 21 | 22 | #include "BaseEngine.h" 23 | #include "Debug.h" 24 | 25 | class PDFEngine : public BaseEngine 26 | { 27 | public: 28 | PDFEngine(BString filename, BString& password); 29 | 30 | virtual ~PDFEngine(); 31 | 32 | virtual BString FileName(void) const; 33 | int PageCount(void) const; 34 | 35 | virtual BString GetProperty(BString name); 36 | 37 | virtual void WriteOutline(BOutlineListView* list); 38 | 39 | virtual std::unique_ptr RenderBitmap(int const& pageNumber,uint32 const& width, 40 | uint32 const& height, int const& rotation = 0); 41 | 42 | private: 43 | virtual std::pair _RenderBitmap(int const& pageNumber); 44 | virtual std::tuple< std::vector, std::vector > 45 | _FindString(BString const& name, int const& page); 46 | 47 | fz_document* fDocument; 48 | fz_context* fContext; 49 | fz_context* fRenderContext; 50 | 51 | fz_page* fPage; 52 | fz_display_list* fList; 53 | fz_device* fDev; 54 | 55 | fz_colorspace* fColorSpace; 56 | 57 | BString fFileName; 58 | BString fPassword; 59 | 60 | pthread_mutex_t fRendermutex = PTHREAD_MUTEX_INITIALIZER; 61 | 62 | Debug out; 63 | }; 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /application/PDFFilter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2011 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | 10 | #include "PDFFilter.h" 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | 17 | static const char* valid_filetypes[] = { 18 | "application/pdf", 19 | "application/djvu", 20 | "application/xps", 21 | NULL 22 | }; 23 | 24 | bool 25 | PDFFilter::Filter(const entry_ref* ref, BNode* node, struct stat_beos* st, 26 | const char* filetype) 27 | { 28 | BEntry entry(ref, true); 29 | if (entry.InitCheck() != B_OK) 30 | return false; 31 | if (entry.IsDirectory()) 32 | return true; 33 | 34 | entry_ref linkedRef; 35 | if (entry.GetRef(&linkedRef) != B_OK) 36 | return false; 37 | 38 | BMimeType mimeType; 39 | if (BMimeType::GuessMimeType(&linkedRef, &mimeType) != B_OK) 40 | return false; 41 | 42 | for (int i = 0; valid_filetypes[i] != nullptr; i++) 43 | if (strcmp(mimeType.Type(), valid_filetypes[i]) == 0) 44 | return true; 45 | 46 | return false; 47 | } 48 | -------------------------------------------------------------------------------- /application/PDFFilter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2011 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #ifndef PDF_FILTER_H 10 | #define PDF_FILTER_H 11 | 12 | #include 13 | 14 | class PDFFilter : public BRefFilter { 15 | public: 16 | bool Filter(const entry_ref* ref, BNode* node, struct stat_beos* st, 17 | const char* filetype); 18 | }; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /application/PageNavigationView.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2012 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #include "PageNavigationView.h" 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include "ImageButton.h" 18 | 19 | using namespace std; 20 | 21 | PageNavigationView::PageNavigationView(unique_ptr message) 22 | : 23 | BGroupView("page_navigation_view", B_HORIZONTAL, 0), 24 | BInvoker(message.release(), NULL, NULL), 25 | fMaxValue(10000) 26 | { 27 | SetFlags(Flags() | B_FRAME_EVENTS); 28 | unique_ptr pageNumberMsg(new BMessage(M_GOTO_PAGE)); 29 | 30 | fPageNC = new NumberControl(move(pageNumberMsg)); 31 | fTotalPagesSV = new BStringView("pages_sv", ""); 32 | 33 | BGroupLayout* layout1; 34 | layout1 = BLayoutBuilder::Group<>(B_HORIZONTAL, 0) 35 | .Add(fPageNC) 36 | .AddGroup(B_VERTICAL, 0) 37 | .AddGlue(0) 38 | .Add(fTotalPagesSV) 39 | .AddGlue(0) 40 | .End() 41 | ; 42 | 43 | BBox* box1 = new BBox("box1"); 44 | box1->SetBorder(B_FANCY_BORDER); 45 | box1->AddChild(layout1->View()); 46 | 47 | fBackButton = new ImageButton("back", 48 | new BMessage(M_GOTO_PREVIOUS_PAGE), 0.3, 1, "Previous page"); 49 | 50 | fNextButton = new ImageButton("next", 51 | new BMessage(M_GOTO_NEXT_PAGE), 0.3, 1, "Next page"); 52 | 53 | BLayoutBuilder::Group<>(this) 54 | .Add(fBackButton) 55 | .Add(box1) 56 | .Add(fNextButton) 57 | ; 58 | } 59 | 60 | 61 | void 62 | PageNavigationView::MessageReceived(BMessage* message) 63 | { 64 | switch (message->what) { 65 | case M_GOTO_PAGE: 66 | SetValue(fPageNC->Value()); 67 | Invoke(); 68 | break; 69 | 70 | case M_GOTO_NEXT_PAGE: 71 | if (fNextButton->PushedLong()) 72 | SetValue(fMaxValue); 73 | else 74 | SetValue(fPageNC->Value() + 1); 75 | 76 | Invoke(); 77 | break; 78 | 79 | case M_GOTO_PREVIOUS_PAGE: 80 | if (fBackButton->PushedLong()) 81 | SetValue(1); 82 | else 83 | SetValue(fPageNC->Value() - 1); 84 | 85 | Invoke(); 86 | break; 87 | 88 | default: 89 | BGroupView::MessageReceived(message); 90 | break; 91 | } 92 | } 93 | 94 | 95 | void 96 | PageNavigationView::AttachedToWindow(void) 97 | { 98 | fNextButton->SetTarget(this); 99 | fBackButton->SetTarget(this); 100 | fPageNC->SetTarget(this); 101 | BGroupView::AttachedToWindow(); 102 | } 103 | 104 | 105 | void 106 | PageNavigationView::FrameResized(float newWidth, float newHeight) 107 | { 108 | fBackButton->SetExplicitMinSize(BSize(newHeight, newHeight)); 109 | fBackButton->SetExplicitMaxSize(BSize(newHeight, newHeight)); 110 | fNextButton->SetExplicitMinSize(BSize(newHeight, newHeight)); 111 | fNextButton->SetExplicitMaxSize(BSize(newHeight, newHeight)); 112 | 113 | BGroupView::FrameResized(newWidth, newHeight); 114 | } 115 | 116 | 117 | void 118 | PageNavigationView::MakeFocus(bool focus) 119 | { 120 | BGroupView::MakeFocus(focus); 121 | } 122 | 123 | 124 | void 125 | PageNavigationView::SetValue(int value) 126 | { 127 | if (value < 1) 128 | value = 1; 129 | else if (value > fMaxValue) 130 | value = fMaxValue; 131 | 132 | fPageNC->SetValue(value); 133 | } 134 | 135 | void 136 | PageNavigationView::SetMaxValue(int const& value) 137 | { 138 | fMaxValue = value; 139 | BString str = " / "; 140 | str << fMaxValue; 141 | fTotalPagesSV->SetText(str); 142 | } 143 | 144 | 145 | int 146 | PageNavigationView::Value(void) 147 | { 148 | return fPageNC->Value(); 149 | } 150 | -------------------------------------------------------------------------------- /application/PageNavigationView.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2012 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #ifndef PAGENAVIGATIONVIEW_H 10 | #define PAGENAVIGATIONVIEW_H 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #include "Debug.h" 19 | #include "ImageButton.h" 20 | #include "NumberControl.h" 21 | 22 | 23 | class PageNavigationView : public BGroupView, public BInvoker 24 | { 25 | public: 26 | PageNavigationView(std::unique_ptr message); 27 | 28 | virtual void FrameResized(float newWidth, float newHeight); 29 | virtual void MessageReceived(BMessage* message); 30 | virtual void AttachedToWindow(void); 31 | virtual void MakeFocus(bool focus); 32 | 33 | int Value(void); 34 | void SetValue(int value); 35 | void SetMaxValue(int const& value); 36 | 37 | enum{ M_GOTO_PAGE = 'ig01', M_GOTO_NEXT_PAGE = 'ig02', 38 | M_GOTO_PREVIOUS_PAGE = 'ig03' 39 | }; 40 | 41 | private: 42 | NumberControl* fPageNC; 43 | BStringView* fTotalPagesSV; 44 | 45 | ImageButton* fBackButton; 46 | ImageButton* fNextButton; 47 | 48 | int fMaxValue; 49 | 50 | Debug out; 51 | }; 52 | 53 | #endif // PAGENAVIGATIONVIEW_H 54 | -------------------------------------------------------------------------------- /application/PasswordRequestWindow.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2012 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #include "PasswordRequestWindow.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "Settings.h" 19 | 20 | PasswordRequestWindow::PasswordRequestWindow() 21 | : 22 | BWindow(BRect(), "Enter Password", B_TITLED_WINDOW_LOOK, 23 | B_MODAL_APP_WINDOW_FEEL, B_ASYNCHRONOUS_CONTROLS 24 | | B_NOT_CLOSABLE | B_NOT_MOVABLE 25 | | B_AUTO_UPDATE_SIZE_LIMITS | B_OUTLINE_RESIZE 26 | | B_NOT_RESIZABLE | B_NOT_MINIMIZABLE | B_NOT_ZOOMABLE ), 27 | fWaiting(true), 28 | fIsOk(false) 29 | { 30 | fPasswordTC = new BTextControl("Password:", "password", NULL); 31 | fPasswordTC->TextView()->HideTyping(true); 32 | fShowCB = new BCheckBox("Show Characters", new BMessage(M_SHOW_CHARS)); 33 | 34 | BButton* cancelButton = new BButton("Cancel", new BMessage(M_CANCEL)); 35 | BButton* okButton = new BButton("OK", new BMessage(M_OK)); 36 | 37 | SetDefaultButton(okButton); 38 | 39 | BLayoutBuilder::Group<>(this, B_VERTICAL, 10) 40 | .SetInsets(10, 10, 10, 10) 41 | .Add(fPasswordTC) 42 | .Add(fShowCB) 43 | .AddGroup(B_HORIZONTAL, 0, 1) 44 | .Add(cancelButton) 45 | .AddStrut(50) 46 | .Add(okButton) 47 | .End() 48 | 49 | .End() 50 | ; 51 | } 52 | 53 | 54 | void 55 | PasswordRequestWindow::MessageReceived(BMessage* message) 56 | { 57 | switch (message->what) { 58 | case M_OK: 59 | fWaiting = false; 60 | fIsOk = true; 61 | Close(); 62 | break; 63 | 64 | case M_CANCEL: 65 | fWaiting = false; 66 | Close(); 67 | break; 68 | 69 | case M_SHOW_CHARS: 70 | if (fShowCB->Value() == 0) 71 | fPasswordTC->TextView()->HideTyping(true); 72 | else 73 | fPasswordTC->TextView()->HideTyping(false); 74 | 75 | fPasswordTC->TextView()->Invalidate(); 76 | fPasswordTC->MakeFocus(); 77 | break; 78 | 79 | default: 80 | BWindow::MessageReceived(message); 81 | break; 82 | } 83 | } 84 | 85 | 86 | std::tuple 87 | PasswordRequestWindow::Go(void) 88 | { 89 | CenterOnScreen(); 90 | Show(); 91 | while (fWaiting) { 92 | usleep(10000); 93 | } 94 | 95 | return std::tuple(fPasswordTC->Text(), fIsOk); 96 | } 97 | -------------------------------------------------------------------------------- /application/PasswordRequestWindow.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2012 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #ifndef PASSWORDREQUESTWINDOW_H 10 | #define PASSWORDREQUESTWINDOW_H 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #include "Debug.h" 19 | 20 | class PasswordRequestWindow : public BWindow 21 | { 22 | public: 23 | PasswordRequestWindow(); 24 | virtual void MessageReceived(BMessage* message); 25 | 26 | std::tuple Go(void); 27 | 28 | enum { 29 | M_CANCEL = 'ic01', M_OK = 'io01', M_SHOW_CHARS = 'is01' 30 | }; 31 | private: 32 | void _Apply(void); 33 | 34 | BWindow* fTarget; 35 | 36 | BTextControl* fPasswordTC; 37 | BCheckBox* fShowCB; 38 | 39 | bool fWaiting; 40 | bool fIsOk; 41 | 42 | Debug out; 43 | }; 44 | 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /application/PreviewView.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2011 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #include "PreviewView.h" 10 | 11 | #include 12 | 13 | #include 14 | 15 | #include "Messages.h" 16 | #include "PDFEngine.h" 17 | #include "DJVUEngine.h" 18 | 19 | 20 | PreviewView::PreviewView(void) 21 | : 22 | BGroupView("preview", B_VERTICAL, 0) 23 | { 24 | SetFlags(Flags() | B_WILL_DRAW); 25 | fColumnOption = new BOptionPopUp("column_option", "", 26 | new BMessage(M_COLUMN_WIDTH)); 27 | fColumnOption->AddOptionAt("Fit Width", FIT_WIDTH, 0); 28 | fColumnOption->AddOptionAt("Small Width", SMALL_COLUMN, 1); 29 | fColumnOption->AddOptionAt("Medium Width", MEDIUM_COLUMN, 2); 30 | fColumnOption->AddOptionAt("Big Width", BIG_COLUMN, 3); 31 | 32 | fBasicPreviewView = new BasicPreviewView(); 33 | 34 | fVScrollBar = new BScrollBar("v_scrollbar", fBasicPreviewView, 0, 10000, 35 | B_VERTICAL); 36 | 37 | BLayoutBuilder::Group<>(this) 38 | .AddGroup(B_HORIZONTAL, 0) 39 | .Add(fColumnOption) 40 | .End() 41 | // .AddStrut(1) 42 | .AddGroup(B_HORIZONTAL, 0) 43 | .Add(fBasicPreviewView) 44 | .Add(fVScrollBar) 45 | .End() 46 | .End() 47 | ; 48 | } 49 | 50 | 51 | void 52 | PreviewView::AttachedToWindow(void) 53 | { 54 | SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 55 | fColumnOption->SetTarget(this); 56 | } 57 | 58 | 59 | void 60 | PreviewView::Show(void) 61 | { 62 | //if (fBasicPreviewView->fEngine == nullptr) 63 | // return; 64 | 65 | BGroupView::Show(); 66 | } 67 | 68 | 69 | 70 | void 71 | PreviewView::MessageReceived(BMessage* message) 72 | { 73 | message->PrintToStream(); 74 | switch (message->what) { 75 | case M_COLUMN_WIDTH: 76 | { 77 | int32 value = 0; 78 | fColumnOption->SelectedOption(nullptr, &value); 79 | fBasicPreviewView->SetColumnWidth(value); 80 | break; 81 | } 82 | 83 | default: 84 | BView::MessageReceived(message); 85 | break; 86 | } 87 | } 88 | 89 | 90 | void 91 | PreviewView::FileChanged(const BString& file, BString const& fileType, 92 | BString& password) 93 | { 94 | fBasicPreviewView->SetFile(file, fileType, password); 95 | Invalidate(); 96 | } 97 | 98 | 99 | void 100 | PreviewView::SelectPage(const int& pageNumber) 101 | { 102 | fBasicPreviewView->SelectPage(pageNumber); 103 | } 104 | 105 | 106 | BasicPreviewView::BasicPreviewView(void) 107 | : 108 | BView(BRect(), "basic_preview_view", B_FOLLOW_ALL, 109 | B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS ), 110 | fOldMousePos(0, 0), 111 | fZoom(1), 112 | fPageHeight(0), 113 | fHSpace(5), 114 | fVSpace(5), 115 | fHMargin(1), 116 | fVMargin(1), 117 | fColumns(1), 118 | fRows(0), 119 | fColumnWidth(0), 120 | fMouseButtons(0), 121 | fCurrentPageNumber(0), 122 | fHighlightPageNumber(0), 123 | fIsPanning(false), 124 | fScrollToCurrentPage(0) 125 | { 126 | fEngine = nullptr; 127 | } 128 | 129 | 130 | void 131 | BasicPreviewView::MessageReceived(BMessage* message) 132 | { 133 | switch (message->what) { 134 | 135 | default: 136 | BView::MessageReceived(message); 137 | break; 138 | } 139 | } 140 | 141 | 142 | void 143 | BasicPreviewView::KeyDown(const char* bytes, int32 numBytes) 144 | { 145 | if (numBytes == 1) { 146 | switch (bytes[0]) { 147 | case B_PAGE_UP: 148 | case B_UP_ARROW: 149 | case B_LEFT_ARROW: 150 | _ScrollUpBigStep(); 151 | break; 152 | 153 | case B_PAGE_DOWN: 154 | case B_DOWN_ARROW: 155 | case B_RIGHT_ARROW: 156 | _ScrollDownBigStep(); 157 | break; 158 | 159 | case B_HOME: 160 | _ShowPage(0); 161 | break; 162 | 163 | case B_END: 164 | _ShowPage(fEngine->PageCount() - 1); 165 | break; 166 | 167 | default: 168 | BView::KeyDown(bytes, numBytes); 169 | break; 170 | } 171 | } 172 | } 173 | 174 | 175 | void 176 | BasicPreviewView::Draw(BRect updateRect) 177 | { 178 | BRect bounds = Bounds(); 179 | 180 | if (fEngine == nullptr) { 181 | BView::Draw(updateRect); 182 | return; 183 | } 184 | 185 | SetHighColor(0, 0, 0, 255); 186 | BPoint where(0, 0); 187 | 188 | if (fColumnWidth > 0 && fColumnWidth < bounds.Width()) { 189 | fRows = ceil(static_cast(_Pages()) / fColumns); 190 | _SetColumns((Bounds().Width() - 2*fHMargin + fHSpace) / (fColumnWidth + fHSpace)); 191 | 192 | fPageHeight = _PageHeight(); 193 | int lowerbound = fCurrentPageNumber; 194 | int upperbound = 2 + (bounds.Height() -fVSpace) / (fPageHeight + fVSpace); 195 | upperbound *= fColumns; 196 | upperbound += fCurrentPageNumber; 197 | 198 | if (upperbound > _Pages()) 199 | upperbound = _Pages(); 200 | 201 | BRect rect; 202 | int i = lowerbound; 203 | where.y = fVMargin + fCurrentRow * (fPageHeight + fVSpace); 204 | for ( ; i < upperbound;) { 205 | where.x = fHMargin; 206 | 207 | for (int j = 0; j < fColumns && i < upperbound; ++j, ++i) { 208 | rect.left = 0; 209 | rect.top = 0; 210 | rect.right = fColumnWidth; 211 | rect.bottom = fPageHeight = _PageHeight(i); 212 | rect.OffsetBySelf(where); 213 | if (rect.Intersects(updateRect)) { 214 | DrawBitmapAsync(_Page(i), rect); 215 | if (i == fHighlightPageNumber) { 216 | SetHighColor(0, 0, 255, 255); 217 | SetPenSize(2); 218 | StrokeRect(rect); 219 | SetHighColor(0, 0, 0, 255); 220 | SetPenSize(1); 221 | } else { 222 | StrokeRect(rect); 223 | } 224 | } 225 | where.x += fColumnWidth + fHSpace; 226 | } 227 | where.y += rect.Height() + fVSpace; 228 | } 229 | fZoom = fColumnWidth / fEngine->Page(upperbound - 1)->Bounds().Width(); 230 | } else { 231 | where.x = fHMargin; 232 | fRows = fEngine->PageCount(); 233 | fPageHeight = _PageHeight(); 234 | float width = bounds.Width() - 2*fHMargin; 235 | int upperbound = bounds.Height() / fPageHeight; 236 | upperbound = upperbound + fCurrentPageNumber + 2; 237 | 238 | if (upperbound > fEngine->PageCount()) 239 | upperbound = fEngine->PageCount(); 240 | 241 | where.y = fVMargin + fCurrentRow * (fPageHeight + fVSpace); 242 | 243 | bool hasDrawn = false; 244 | for (int i = fCurrentPageNumber; i < upperbound; ++i) { 245 | fPageHeight = _PageHeight(i); 246 | BRect rect(0, 0, width, fPageHeight); 247 | rect.OffsetBySelf(where); 248 | if (rect.Intersects(updateRect)){ 249 | hasDrawn = true; 250 | DrawBitmapAsync(_Page(i), rect); 251 | if (i == fHighlightPageNumber) { 252 | SetHighColor(0, 0, 255, 255); 253 | SetPenSize(2); 254 | } else { 255 | SetHighColor(0, 0, 0, 255); 256 | SetPenSize(1); 257 | } 258 | StrokeRect(rect); 259 | } else if (hasDrawn) { 260 | break; 261 | } 262 | where.y += (fPageHeight + fVSpace); 263 | } 264 | fZoom = width / (fZoom * fEngine->Page(upperbound - 1)->Bounds().Width()); 265 | } 266 | } 267 | 268 | 269 | void 270 | BasicPreviewView::FrameResized(float newWidth, float newHeight) 271 | { 272 | BView::FrameResized(newWidth, newHeight); 273 | if (fEngine == nullptr) 274 | return; 275 | 276 | _ShowPage(fCurrentPageNumber); 277 | _AdaptCache(); 278 | } 279 | 280 | 281 | void 282 | BasicPreviewView::SetFile(BString file, BString fileType, BString& password) 283 | { 284 | delete fEngine; 285 | if (fileType == "djvu") 286 | fEngine = new DJVUEngine(file, password); 287 | else if (fileType == "pdf" || fileType == "xps") 288 | fEngine = new PDFEngine(file, password); 289 | else 290 | throw B_ERROR; 291 | 292 | _AdaptScrollBarRange(); 293 | Invalidate(); 294 | } 295 | 296 | 297 | void 298 | BasicPreviewView::MouseMoved(BPoint where, uint32 code, 299 | const BMessage* dragMessage) 300 | { 301 | switch (code) { 302 | case B_EXITED_VIEW: 303 | fIsPanning = false; 304 | break; 305 | 306 | default: 307 | break; 308 | } 309 | 310 | if (fIsPanning == true) { 311 | BPoint delta = fOldMousePos - where; 312 | 313 | ScrollBar(B_VERTICAL)->SetValue( 314 | ScrollBar(B_VERTICAL)->Value() + delta.y); 315 | } 316 | 317 | BView::MouseMoved(where, code, dragMessage); 318 | } 319 | 320 | 321 | void 322 | BasicPreviewView::MouseDown(BPoint where) 323 | { 324 | MakeFocus(true); 325 | GetMouse(&fOldMousePos, &fMouseButtons); 326 | 327 | int32 clicks = 0; 328 | Window()->CurrentMessage()->FindInt32("clicks", &clicks); 329 | 330 | if (clicks == 2) { 331 | fHighlightPageNumber = _ConvertToPage(fOldMousePos); 332 | _GoToPage(fHighlightPageNumber); 333 | Invalidate(); 334 | } else { 335 | fIsPanning = true; 336 | } 337 | 338 | BView::MouseDown(where); 339 | } 340 | 341 | 342 | void 343 | BasicPreviewView::MouseUp(BPoint where) 344 | { 345 | fIsPanning = false; 346 | 347 | BView::MouseUp(where); 348 | } 349 | 350 | 351 | void 352 | BasicPreviewView::ScrollTo(BPoint where) 353 | { 354 | if (fEngine == nullptr) 355 | return; 356 | 357 | BView::ScrollTo(where); 358 | 359 | where.x = fHMargin; 360 | int row = _ConvertToRow(where); 361 | 362 | if (row != fCurrentRow) { 363 | fCurrentRow = row; 364 | fCurrentPageNumber = row * fColumns; 365 | _AdaptScrollBarRange(); 366 | } 367 | } 368 | 369 | 370 | inline void 371 | BasicPreviewView::_GoToPage(int pageNumber) 372 | { 373 | BMessage msg(MSG_GOTO_PAGE); 374 | msg.AddInt32("info", pageNumber); 375 | Window()->PostMessage(&msg); 376 | } 377 | 378 | 379 | inline int 380 | BasicPreviewView::_ConvertToPage(BPoint const& where) 381 | { 382 | if (fEngine == nullptr) 383 | return 0; 384 | 385 | if (fColumns == 1) { 386 | return _ConvertToRow(where); 387 | } else { 388 | int x = (where.x - fHMargin) / (fColumnWidth + fHSpace); 389 | int y = (where.y - fVMargin) / (_PageHeight() + fVSpace); 390 | 391 | return x + y*fColumns; 392 | } 393 | } 394 | 395 | 396 | inline void 397 | BasicPreviewView::_AdaptScrollBarRange(void) 398 | { 399 | if (fEngine == nullptr) 400 | return; 401 | 402 | if (fColumnWidth == 0) { 403 | ScrollBar(B_VERTICAL)->SetRange(0, fVMargin + (fVSpace + _PageHeight()) * fRows 404 | - Bounds().Height()); 405 | 406 | float bigStepV = std::min(Bounds().Height(), _PageHeight()); 407 | float smallStepV = Bounds().Height() / 27; 408 | ScrollBar(B_VERTICAL)->SetSteps(smallStepV, bigStepV); 409 | } else { 410 | ScrollBar(B_VERTICAL)->SetRange(0, fVMargin + (fVSpace + _PageHeight()) * fRows 411 | - Bounds().Height()); 412 | 413 | float bigStepV = Bounds().Height(); 414 | float smallStepV = Bounds().Height() / 27; 415 | ScrollBar(B_VERTICAL)->SetSteps(smallStepV, bigStepV); 416 | } 417 | } 418 | 419 | 420 | void 421 | BasicPreviewView::_ScrollDownBigStep(void) 422 | { 423 | float height = Bounds().Height(); 424 | int value1 = ScrollBar(B_VERTICAL)->Value() + height; 425 | 426 | ScrollBar(B_VERTICAL)->SetValue(value1); 427 | } 428 | 429 | 430 | void 431 | BasicPreviewView::_ScrollUpBigStep(void) 432 | { 433 | int value1 = ScrollBar(B_VERTICAL)->Value() - Bounds().Height(); 434 | ScrollBar(B_VERTICAL)->SetValue(value1); 435 | } 436 | 437 | 438 | inline float 439 | BasicPreviewView::_PageHeight(const int& pageNumber) 440 | { 441 | if (fColumnWidth == 0) { 442 | float zoom = Bounds().Width() / fEngine->Page(pageNumber)->Bounds().Width(); 443 | return fEngine->Page(pageNumber)->Bounds().Height() * zoom; 444 | } else { 445 | float zoom = fColumnWidth / fEngine->Page(pageNumber)->Bounds().Width(); 446 | return fEngine->Page(pageNumber)->Bounds().Height() * zoom; 447 | } 448 | } 449 | 450 | 451 | inline float 452 | BasicPreviewView::_PageHeight(void) 453 | { 454 | return _PageHeight(fCurrentPageNumber); 455 | } 456 | 457 | 458 | inline float 459 | BasicPreviewView::_PageWidth(void) 460 | { 461 | if (fColumnWidth == 0) 462 | return Bounds().Width(); 463 | else 464 | return fColumnWidth; 465 | } 466 | 467 | 468 | inline int 469 | BasicPreviewView::_Pages(void) 470 | { 471 | if (fEngine == nullptr) 472 | return 0; 473 | 474 | return fEngine->PageCount(); 475 | } 476 | 477 | 478 | #if 0 479 | void 480 | BasicPreviewView::Pulse(void) 481 | { 482 | if (fZoom != 1) { 483 | fEngine->MultiplyZoom(fZoom); 484 | fZoom = 1; 485 | Invalidate(); 486 | } 487 | } 488 | #endif 489 | 490 | 491 | inline void 492 | BasicPreviewView::_ShowPage(const int& pageNumber) 493 | { 494 | _SetScrollBarAtPage(pageNumber); 495 | Invalidate(); 496 | } 497 | 498 | 499 | inline void 500 | BasicPreviewView::_ShowPage(void) 501 | { 502 | _ShowPage(fCurrentPageNumber); 503 | } 504 | 505 | 506 | inline void 507 | BasicPreviewView::_SetScrollBarAtPage(int pageNumber) 508 | { 509 | _AdaptScrollBarRange(); 510 | ScrollBar(B_VERTICAL)->SetValue(fVMargin + 511 | (_PageHeight(pageNumber) + fVSpace) * _PageToRow(pageNumber)); 512 | } 513 | 514 | 515 | void 516 | BasicPreviewView::SetColumnWidth(const int32& width) 517 | { 518 | if (fColumnWidth == width || fEngine == nullptr) 519 | return; 520 | 521 | // TODO: Not a good solution 522 | BBitmap* bitmap = fEngine->Page(fCurrentPageNumber); 523 | while (bitmap == nullptr) { 524 | ++fCurrentPageNumber; 525 | if (fCurrentPageNumber >= fEngine->PageCount()) 526 | return; 527 | 528 | bitmap = fEngine->Page(fCurrentPageNumber); 529 | } 530 | 531 | if (bitmap == nullptr) 532 | !out << "NULL" << endl; 533 | 534 | int page = fCurrentPageNumber; 535 | 536 | fColumnWidth = width; 537 | fPageHeight = _PageHeight(); 538 | 539 | 540 | if (width <= 0) { 541 | fZoom = Bounds().Width() / bitmap->Bounds().Width(); 542 | fColumns = 1; 543 | _AdaptCache(); 544 | } else { 545 | fZoom = fColumnWidth / bitmap->Bounds().Width(); 546 | fColumns = (Bounds().Width() - 2*fHMargin + fHSpace) / (fColumnWidth + fHSpace); 547 | if (fColumns < 1) 548 | fColumns = 1; 549 | 550 | _AdaptCache(); 551 | } 552 | _ShowPage(page); 553 | } 554 | 555 | 556 | void 557 | BasicPreviewView::SelectPage(const int& pageNumber) 558 | { 559 | fHighlightPageNumber = pageNumber; 560 | // _ShowPage(fHighlightPageNumber); 561 | } 562 | 563 | 564 | int 565 | BasicPreviewView::_ConvertToRow(const BPoint& where) 566 | { 567 | return (where.y - fVMargin) / (_PageHeight() + fVSpace); 568 | } 569 | 570 | 571 | void 572 | BasicPreviewView::_AdaptCache(void) 573 | { 574 | int cache; 575 | if (fColumnWidth == 0) 576 | cache = 16; 577 | else 578 | cache = 6; 579 | 580 | int size = cache * fColumns * (Bounds().Height() - 2*fVMargin) / (_PageHeight() + fVSpace); 581 | 582 | /* 583 | if (fColumnWidth == 0) { 584 | fZoom = Bounds().Width() / fEngine->Page(fCurrentPageNumber)->Bounds().Width(); 585 | } else { 586 | fZoom = fColumnWidth / fEngine->Page(fCurrentPageNumber)->Bounds().Width(); 587 | } 588 | */ 589 | fEngine->MultiplyZoom(fZoom); 590 | fZoom = 1; 591 | 592 | fEngine->SetCacheSize(size, size); 593 | } 594 | 595 | 596 | void 597 | BasicPreviewView::_SetColumns(const int& columns) 598 | { 599 | if (fColumns == columns) 600 | return; 601 | 602 | fColumns = columns; 603 | _AdaptCache(); 604 | _AdaptScrollBarRange(); 605 | } 606 | 607 | 608 | BBitmap* 609 | BasicPreviewView::_Page(const int& pageNumber) 610 | { 611 | return fEngine->Page(pageNumber); 612 | } 613 | 614 | 615 | int 616 | BasicPreviewView::_PageToRow(const int& pageNumber) 617 | { 618 | if (fColumns < 1) 619 | throw std::range_error("fColumns < 1"); 620 | 621 | return pageNumber / fColumns; 622 | } 623 | -------------------------------------------------------------------------------- /application/PreviewView.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2012 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #ifndef PREVIEWVIEW_H 10 | #define PREVIEWVIEW_H 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "BaseEngine.h" 23 | #include "Debug.h" 24 | 25 | class BasicPreviewView : public BView 26 | { 27 | public: 28 | BasicPreviewView(void); 29 | 30 | virtual void Draw(BRect updateRect); 31 | virtual void FrameResized(float newWidth, float newHeight); 32 | virtual void MessageReceived(BMessage* message); 33 | virtual void KeyDown(const char* bytes, int32 numBytes); 34 | virtual void MouseDown(BPoint where); 35 | virtual void MouseUp(BPoint where); 36 | virtual void MouseMoved(BPoint where, uint32 code, 37 | const BMessage* dragMessage); 38 | virtual void ScrollTo(BPoint where); 39 | 40 | void SetFile(BString file, BString fileType, BString& password); 41 | void SetColumnWidth(const int32& width); 42 | void SelectPage(const int& pageNumber); 43 | 44 | friend class PreviewView; 45 | 46 | private: 47 | void _AdaptScrollBarRange(void); 48 | void _GoToPage(int pageNumber); 49 | void _ScrollDownBigStep(void); 50 | void _ScrollUpBigStep(void); 51 | int _ConvertToPage(BPoint const& where); 52 | inline int _ConvertToRow(const BPoint& where); 53 | inline float _PageHeight(const int& pageNumber); 54 | inline float _PageHeight(void); 55 | inline float _PageWidth(void); 56 | inline int _Pages(void); 57 | inline void _ShowPage(const int& pageNumber); 58 | inline void _ShowPage(void); 59 | inline void _SetScrollBarAtPage(int pageNumber); 60 | inline void _AdaptCache(void); 61 | inline void _SetColumns(const int& columns); 62 | inline BBitmap* _Page(const int& pageNumber); 63 | inline int _PageToRow(const int& pageNumber); 64 | 65 | 66 | BaseEngine* fEngine; 67 | BPoint fOldMousePos; 68 | float fZoom; 69 | float fPageHeight; 70 | int fHSpace; 71 | int fVSpace; 72 | int fHMargin; 73 | int fVMargin; 74 | int fColumns; 75 | int fRows; 76 | int fCurrentRow; 77 | 78 | int32 fColumnWidth; 79 | uint32 fMouseButtons; 80 | 81 | int fCurrentPageNumber; 82 | int fHighlightPageNumber; 83 | bool fIsPanning; 84 | int fScrollToCurrentPage; 85 | 86 | Debug out; 87 | }; 88 | 89 | 90 | class PreviewView : public BGroupView 91 | { 92 | public: 93 | PreviewView(void); 94 | virtual void MessageReceived(BMessage* message); 95 | virtual void AttachedToWindow(void); 96 | virtual void Show(void); 97 | virtual void FileChanged(const BString& file, BString const& fileType, 98 | BString& password); 99 | 100 | void SetFile(BString file, BString& password); 101 | void SelectPage(const int& pageNumber); 102 | 103 | 104 | BaseEngine* Engine(void) 105 | { 106 | return fBasicPreviewView->fEngine; 107 | } 108 | 109 | private: 110 | BOptionPopUp* fColumnOption; 111 | BasicPreviewView* fBasicPreviewView; 112 | 113 | BScrollBar* fVScrollBar; 114 | BScrollBar* fHScrollBar; 115 | 116 | Debug out; 117 | 118 | enum{ 119 | FIT_WIDTH = 0, SMALL_COLUMN = 75, MEDIUM_COLUMN = 125, BIG_COLUMN = 200 120 | }; 121 | 122 | enum{ 123 | M_COLUMN_WIDTH = 'ic01' 124 | }; 125 | }; 126 | 127 | #endif 128 | -------------------------------------------------------------------------------- /application/PrintPreviewView.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2012 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | 10 | #include "PrintPreviewView.h" 11 | 12 | #include 13 | 14 | PrintPreviewView::PrintPreviewView(void) 15 | : 16 | BView(BRect(), "print_preview_view", B_FOLLOW_ALL, 17 | B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS ) 18 | { 19 | SetViewColor(B_TRANSPARENT_32_BIT); 20 | //SetDrawingMode(B_OP_ALPHA); 21 | //SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); 22 | 23 | Invalidate(); 24 | } 25 | 26 | 27 | void 28 | PrintPreviewView::MessageReceived(BMessage* message) 29 | { 30 | switch (message->what) { 31 | 32 | default: 33 | BView::MessageReceived(message); 34 | break; 35 | } 36 | } 37 | 38 | 39 | void 40 | PrintPreviewView::KeyDown(const char* bytes, int32 numBytes) 41 | { 42 | if (numBytes == 1) { 43 | switch (bytes[0]) { 44 | default: 45 | BView::KeyDown(bytes, numBytes); 46 | break; 47 | } 48 | } 49 | } 50 | 51 | #if 0 52 | void 53 | PrintPreviewView::AllAttached(void) 54 | { 55 | Window()->SetPulseRate(1E6); 56 | BView::AllAttached(); 57 | } 58 | #endif 59 | 60 | 61 | void 62 | PrintPreviewView::Draw(BRect updateRect) 63 | { 64 | BRect bounds = Bounds(); 65 | SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 66 | FillRect(bounds); 67 | 68 | 69 | SetHighColor(0, 0, 0, 255); 70 | BPoint where(0, 0); 71 | 72 | SetPenSize(2); 73 | StrokeRect(bounds); 74 | Sync(); 75 | BView::Draw(updateRect); 76 | } 77 | 78 | 79 | void 80 | PrintPreviewView::FrameResized(float newWidth, float newHeight) 81 | { 82 | 83 | BView::FrameResized(newWidth, newHeight); 84 | } 85 | 86 | 87 | void 88 | PrintPreviewView::MouseMoved(BPoint where, uint32 code, 89 | const BMessage* dragMessage) 90 | { 91 | 92 | 93 | BView::MouseMoved(where, code, dragMessage); 94 | } 95 | 96 | 97 | void 98 | PrintPreviewView::MouseDown(BPoint where) 99 | { 100 | MakeFocus(true); 101 | //GetMouse(&fOldMousePos, &fMouseButtons); 102 | 103 | int32 clicks = 0; 104 | Window()->CurrentMessage()->FindInt32("clicks", &clicks); 105 | 106 | if (clicks == 2) { 107 | 108 | } 109 | 110 | BView::MouseDown(where); 111 | } 112 | 113 | 114 | void 115 | PrintPreviewView::MouseUp(BPoint where) 116 | { 117 | 118 | BView::MouseUp(where); 119 | } 120 | 121 | 122 | -------------------------------------------------------------------------------- /application/PrintPreviewView.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2012 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #ifndef PRINTPREVIEW_H 10 | #define PRINTPREVIEW_H 11 | 12 | #include 13 | 14 | #include "Debug.h" 15 | 16 | class PrintPreviewView : public BView 17 | { 18 | public: 19 | PrintPreviewView(void); 20 | 21 | virtual void Draw(BRect updateRect); 22 | virtual void FrameResized(float newWidth, float newHeight); 23 | virtual void MessageReceived(BMessage* message); 24 | virtual void KeyDown(const char* bytes, int32 numBytes); 25 | virtual void MouseDown(BPoint where); 26 | virtual void MouseUp(BPoint where); 27 | virtual void MouseMoved(BPoint where, uint32 code, 28 | const BMessage* dragMessage); 29 | 30 | private: 31 | 32 | Debug out; 33 | }; 34 | 35 | #endif // PRINTPREVIEW_H 36 | -------------------------------------------------------------------------------- /application/PrintingWindow.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2012 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #ifndef PRINTINGWINDOW_H 10 | #define PRINTINGWINDOW_H 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "Debug.h" 21 | #include "DocumentView.h" 22 | #include "PageNavigationView.h" 23 | #include "PrintPreviewView.h" 24 | 25 | class PrintingWindow : public BWindow 26 | { 27 | public: 28 | PrintingWindow(BWindow* window, DocumentView* doc); 29 | virtual void MessageReceived(BMessage* message); 30 | virtual bool QuitRequested(void); 31 | 32 | enum { 33 | M_CANCEL = 'ic01', 34 | M_HELP = 'ih01', 35 | M_OK = 'io01', 36 | M_PAGENUMBER = 'ip01', 37 | M_PAGES_PER_SHEET = 'ip02', 38 | M_PAGE_ORDER = 'ip03', 39 | M_SCALING = 'is01', 40 | }; 41 | 42 | enum { 43 | FIT_MARGINS, FIT_PAGE, MULTIPLE_PAGES, 44 | SCALE_CUSTOM, SCALE_NONE, 45 | }; 46 | 47 | enum { 48 | ORDER_HORIZONTAL, ORDER_HORIZONTAL_R, 49 | ORDER_VERTICAL, ORDER_VERTICAL_R, 50 | }; 51 | 52 | private: 53 | void _LoadSettings(void); 54 | void _SaveSettings(void); 55 | 56 | BWindow* fTargetWindow; 57 | 58 | BGroupLayout* fScaleCLI1; 59 | BGroupLayout* fScaleCLI2; 60 | BGroupLayout* fMultiplePagesCLI1; 61 | BGroupLayout* fMultiplePagesCLI2; 62 | 63 | BCardLayout* fCardLayout1; 64 | BCardLayout* fCardLayout2; 65 | 66 | BOptionPopUp* fNameOP; 67 | BOptionPopUp* fScalingTypeOP; 68 | BOptionPopUp* fPagesPerSheetOP; 69 | BOptionPopUp* fPageOrderOP; 70 | 71 | BStringView* fStatusSV; 72 | BStringView* fTypeSV; 73 | 74 | BTextControl* fPageFromTC; 75 | BTextControl* fPageToTC; 76 | BTextControl* fPagesTC; 77 | BTextControl* fCopiesTC; 78 | BTextControl* fPreviewPageTC; 79 | BTextControl* fScaleTC; 80 | BTextControl* fXPagesPerSheetTC; 81 | BTextControl* fYPagesPerSheetTC; 82 | 83 | 84 | 85 | BRadioButton* fAllRB; 86 | BRadioButton* fCurrentViewRB; 87 | BRadioButton* fCurrentPageRB; 88 | BRadioButton* fPageFromToRB; 89 | BRadioButton* fPagesRB; 90 | 91 | BCheckBox* fCollateCB; 92 | BCheckBox* fReverseCB; 93 | 94 | DocumentView* fDocument; 95 | 96 | PrintPreviewView* fPrintPreviewView; 97 | 98 | PageNavigationView* fPageNavigationView; 99 | 100 | Debug out; 101 | }; 102 | 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /application/SearchView.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2011 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #include "SearchView.h" 10 | 11 | #include 12 | 13 | #include 14 | #include "Flags.h" 15 | #include "Messages.h" 16 | 17 | 18 | SearchListView::SearchListView(void) 19 | : 20 | BColumnListView("search_list_view", 0) 21 | { 22 | 23 | } 24 | 25 | 26 | void 27 | SearchListView::ItemInvoked(void) 28 | { 29 | BIntegerField* pageField = (BIntegerField*)CurrentSelection()->GetField(0); 30 | 31 | if (pageField == nullptr) 32 | return; 33 | 34 | BMessage msg(MSG_HIGHLIGHT_RECT); 35 | msg.AddInt32("page", pageField->Value() - 1); 36 | msg.AddRect("rect", fRectVec[IndexOf(CurrentSelection())]); 37 | Window()->PostMessage(&msg); 38 | 39 | BColumnListView::ItemInvoked(); 40 | } 41 | 42 | 43 | void 44 | SearchListView::Clear(void) 45 | { 46 | fRectVec.clear(); 47 | BColumnListView::Clear(); 48 | ScrollTo(BPoint(0, 0)); 49 | } 50 | 51 | 52 | SearchView::SearchView(void) 53 | : 54 | BGroupView("find", B_VERTICAL, 0) 55 | { 56 | fSearchTC = new BTextControl("", "", new BMessage(M_TEXT_CHANGED)); 57 | fStartButton = new BButton("Start", new BMessage(M_START)); 58 | fStartButton->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, B_ALIGN_MIDDLE)); 59 | fMatchCaseCB = new BCheckBox("Match Case"); 60 | fWholeWordCB = new BCheckBox("Whole Word"); 61 | 62 | fSearchListView = new SearchListView(); 63 | 64 | BColumn* pageColumn = new BIntegerColumn("pg.", 45, 0, 1000); 65 | BColumn* contextColumn = new BStringColumn("Context", 500, 0, 1000, true); 66 | fSearchListView->AddColumn(pageColumn, 0); 67 | fSearchListView->AddColumn(contextColumn, 1); 68 | fSearchListView->SetSortColumn(pageColumn, true, true); 69 | fSearchListView->SetSortingEnabled(false); 70 | 71 | 72 | fVScrollBar = new BScrollBar("v_scrollbar", 73 | fSearchListView, 0, 2000, B_VERTICAL); 74 | fHScrollBar = new BScrollBar("h_scrollbar", 75 | fSearchListView, 0, 100, B_HORIZONTAL); 76 | 77 | BLayoutBuilder::Group<>(this) 78 | .Add(fSearchTC) 79 | .AddGroup(B_HORIZONTAL, 0) 80 | .Add(fStartButton) 81 | .AddGlue(0) 82 | .End() 83 | .Add(fMatchCaseCB) 84 | .Add(fWholeWordCB) 85 | .Add(fSearchListView) 86 | .End() 87 | ; 88 | } 89 | 90 | 91 | void 92 | SearchView::AttachedToWindow(void) 93 | { 94 | fStartButton->SetTarget(this); 95 | fSearchTC->SetTarget(this); 96 | } 97 | 98 | 99 | void 100 | SearchView::MessageReceived(BMessage* message) 101 | { 102 | switch (message->what) { 103 | case M_START: 104 | { 105 | fSearchTC->MakeFocus(false); 106 | fSearchListView->Clear(); 107 | int32 flag = 0; 108 | 109 | if (fMatchCaseCB->Value() != false) 110 | flag |= SEARCH_MATCH_CASE; 111 | 112 | if (fWholeWordCB->Value() != false) 113 | flag |= SEARCH_WHOLE_WORD; 114 | 115 | fEngine->FindString(fSearchTC->Text(), Window(), this, flag); 116 | break; 117 | } 118 | 119 | case M_TEXT_CHANGED: 120 | { 121 | fSearchListView->Clear(); 122 | int32 flag = 0; 123 | 124 | if (fMatchCaseCB->Value() != false) 125 | flag |= SEARCH_MATCH_CASE; 126 | 127 | if (fWholeWordCB->Value() != false) 128 | flag |= SEARCH_WHOLE_WORD; 129 | 130 | fEngine->FindString(fSearchTC->Text(), Window(), this, flag); 131 | break; 132 | } 133 | 134 | case MSG_SEARCH_RESULT: 135 | { 136 | int32 page = 0; 137 | message->FindInt32("page", &page); 138 | BString context; 139 | message->FindString("context", &context); 140 | BRect rect; 141 | message->FindRect("rect", &rect); 142 | fSearchListView->fRectVec.push_back(rect); 143 | 144 | BRow* row = new BRow(); 145 | row->SetField(new BIntegerField(page + 1), 0); 146 | row->SetField(new BStringField(context), 1); 147 | fSearchListView->AddRow(row); 148 | 149 | break; 150 | } 151 | 152 | default: 153 | BGroupView::MessageReceived(message); 154 | break; 155 | } 156 | } 157 | 158 | 159 | void 160 | SearchView::EngineChanged(BaseEngine* engine) 161 | { 162 | if (engine == nullptr) 163 | return; 164 | 165 | fEngine = engine; 166 | 167 | fSearchListView->Clear(); 168 | } 169 | -------------------------------------------------------------------------------- /application/SearchView.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright 2011-2011 Haiku Inc. All rights reserved. 4 | * Distributed under the terms of the MIT License. 5 | * 6 | * Authors: 7 | * Ciprian Nedisan (cipri) 8 | * 9 | */ 10 | #ifndef SEARCHVIEW_H 11 | #define SEARCHVIEW_H 12 | 13 | #include 14 | 15 | extern "C" { 16 | #include 17 | } 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | #include "Debug.h" 30 | #include "BaseEngine.h" 31 | 32 | 33 | class SearchListView : public BColumnListView 34 | { 35 | public: 36 | SearchListView(void); 37 | virtual void ItemInvoked(void); 38 | 39 | void Clear(void); 40 | 41 | friend class SearchView; 42 | 43 | private: 44 | 45 | std::vector fRectVec; 46 | Debug out; 47 | 48 | }; 49 | 50 | 51 | class SearchView : public BGroupView 52 | { 53 | public: 54 | SearchView(void); 55 | virtual void MessageReceived(BMessage* message); 56 | virtual void AttachedToWindow(void); 57 | 58 | virtual void EngineChanged(BaseEngine* engine); 59 | 60 | enum{ 61 | M_START = 'is01', M_TEXT_CHANGED = 'it01' 62 | }; 63 | 64 | private: 65 | BScrollBar* fVScrollBar; 66 | BScrollBar* fHScrollBar; 67 | 68 | BButton* fStartButton; 69 | BCheckBox* fWholeWordCB; 70 | BCheckBox* fMatchCaseCB; 71 | BTextControl* fSearchTC; 72 | 73 | SearchListView* fSearchListView; 74 | 75 | BaseEngine* fEngine; 76 | }; 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /application/Settings.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2012 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #ifndef SETTINGS_H 10 | #define SETTINGS_H 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "Debug.h" 22 | #include "Tools.h" 23 | 24 | class Settings 25 | { 26 | public: 27 | Settings(BString name) 28 | : 29 | fName(name), 30 | fLabel("") 31 | { 32 | fLoadMessage = nullptr; 33 | fSaveMessage = nullptr; 34 | 35 | fAppName = Tools::AppName().Capitalize(); 36 | fSettings = new BMessage(); 37 | _Load(fSettings); 38 | } 39 | 40 | 41 | ~Settings() 42 | { 43 | delete fLoadMessage; 44 | delete fSaveMessage; 45 | delete fSettings; 46 | } 47 | 48 | 49 | void Clear(void) 50 | { 51 | if (fName == "") 52 | return; 53 | 54 | delete fSaveMessage; 55 | fSaveMessage = new BMessage(); 56 | _Save(); 57 | 58 | } 59 | 60 | 61 | void ClearAll(void) 62 | { 63 | delete fSaveMessage; 64 | fSaveMessage = new BMessage(); 65 | delete fSettings; 66 | fSettings = new BMessage(); 67 | _Save(); 68 | // TODO: better delete file and directory 69 | 70 | } 71 | 72 | 73 | Settings& operator<<(std::ostream& (*f)(std::ostream&)) 74 | { 75 | if (f == static_cast(std::endl)) { 76 | _Save(); 77 | delete fSettings; 78 | fSettings = nullptr; 79 | delete fLoadMessage; 80 | fLoadMessage = nullptr; 81 | delete fSaveMessage; 82 | fSaveMessage = nullptr; 83 | } 84 | 85 | return *this; 86 | } 87 | 88 | 89 | Settings& operator<<(BString const& str) 90 | { 91 | if (fLabel.Length() == 0) { 92 | fLabel = str; 93 | return *this; 94 | } 95 | 96 | _CheckSaveNull(); 97 | 98 | BString temp; 99 | if (fSaveMessage->FindString(fLabel, 0, &temp) == B_OK) 100 | fSaveMessage->ReplaceString(fLabel, str); 101 | else 102 | fSaveMessage->AddString(fLabel, str); 103 | 104 | fLabel = ""; 105 | 106 | return *this; 107 | } 108 | 109 | /* 110 | Settings& operator<<(bool value) 111 | { 112 | int32 newvalue = static_cast(value); 113 | 114 | if (fLabel.Length() == 0) { 115 | return *this; 116 | } else { 117 | if (fSaveMessage == nullptr) { 118 | fSaveMessage = new BMessage(); 119 | fSettings->FindMessage(fName, 0, fSaveMessage); 120 | } 121 | 122 | int32 temp = 0; 123 | if (fSaveMessage->FindInt32(fLabel, 0, &temp) == B_OK) 124 | fSaveMessage->ReplaceInt32(fLabel, newvalue); 125 | else 126 | fSaveMessage->AddInt32(fLabel, newvalue); 127 | 128 | fLabel = ""; 129 | } 130 | 131 | return *this; 132 | } 133 | */ 134 | 135 | Settings& operator<<(int32 value) 136 | { 137 | if (fLabel.Length() == 0) 138 | return *this; 139 | 140 | _CheckSaveNull(); 141 | 142 | int32 temp = 0; 143 | if (fSaveMessage->FindInt32(fLabel, 0, &temp) == B_OK) 144 | fSaveMessage->ReplaceInt32(fLabel, value); 145 | else 146 | fSaveMessage->AddInt32(fLabel, value); 147 | 148 | fLabel = ""; 149 | 150 | return *this; 151 | } 152 | 153 | 154 | Settings& operator<<(float value) 155 | { 156 | if (fLabel.Length() == 0) 157 | return *this; 158 | 159 | _CheckSaveNull(); 160 | 161 | float temp = 0; 162 | if (fSaveMessage->FindFloat(fLabel, 0, &temp) == B_OK) 163 | fSaveMessage->ReplaceFloat(fLabel, value); 164 | else 165 | fSaveMessage->AddFloat(fLabel, value); 166 | 167 | fLabel = ""; 168 | 169 | return *this; 170 | } 171 | 172 | 173 | Settings& operator<<(BRect value) 174 | { 175 | if (fLabel.Length() == 0) 176 | return *this; 177 | 178 | _CheckSaveNull(); 179 | 180 | BRect temp; 181 | if (fSaveMessage->FindRect(fLabel, 0, &temp) == B_OK) 182 | fSaveMessage->ReplaceRect(fLabel, value); 183 | else 184 | fSaveMessage->AddRect(fLabel, value); 185 | 186 | fLabel = ""; 187 | 188 | return *this; 189 | } 190 | 191 | 192 | Settings& operator>>(BString & str) 193 | { 194 | if (fLabel.Length() == 0) 195 | return *this; 196 | 197 | _CheckLoadNull(); 198 | 199 | BString temp = ""; 200 | if (fLoadMessage->FindString(fLabel, 0, &temp) == B_OK) 201 | str = temp; 202 | 203 | fLabel = ""; 204 | return *this; 205 | } 206 | 207 | /* 208 | Settings& operator>>(bool & value) 209 | { 210 | if (fLabel.Length() == 0) 211 | return *this; 212 | 213 | if (fLoadMessage == nullptr) { 214 | fLoadMessage = new BMessage(); 215 | fSettings->FindMessage(fName, 0, fLoadMessage); 216 | } 217 | 218 | bool temp = 0; 219 | if (fLoadMessage->FindBool(fLabel, 0, &temp) == B_OK) 220 | value = temp; 221 | 222 | fLabel = ""; 223 | return *this; 224 | } 225 | */ 226 | 227 | Settings& operator>>(int32 & value) 228 | { 229 | if (fLabel.Length() == 0) 230 | return *this; 231 | 232 | _CheckLoadNull(); 233 | 234 | int32 temp = 0; 235 | if (fLoadMessage->FindInt32(fLabel, 0, &temp) == B_OK) 236 | value = temp; 237 | 238 | fLabel = ""; 239 | return *this; 240 | } 241 | 242 | 243 | Settings& operator>>(float & value) 244 | { 245 | if (fLabel.Length() == 0) 246 | return *this; 247 | 248 | _CheckLoadNull(); 249 | 250 | float temp = 0; 251 | if (fLoadMessage->FindFloat(fLabel, 0, &temp) == B_OK) 252 | value = temp; 253 | 254 | fLabel = ""; 255 | return *this; 256 | } 257 | 258 | 259 | Settings& operator>>(BRect & value) 260 | { 261 | if (fLabel.Length() == 0) 262 | return *this; 263 | 264 | _CheckLoadNull(); 265 | 266 | BRect temp; 267 | if (fLoadMessage->FindRect(fLabel, 0, &temp) == B_OK) 268 | value = temp; 269 | 270 | fLabel = ""; 271 | return *this; 272 | } 273 | 274 | private: 275 | 276 | status_t _Open(BFile& file, uint32 mode) 277 | { 278 | BPath path; 279 | if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) 280 | return B_ERROR; 281 | 282 | path.Append(fAppName); 283 | create_directory(path.Path(), 0755); 284 | path.Append(fAppName); 285 | return file.SetTo(path.Path(), mode); 286 | } 287 | 288 | 289 | status_t _Save() 290 | { 291 | BFile file; 292 | status_t status = _Open(file, B_WRITE_ONLY | B_CREATE_FILE 293 | | B_ERASE_FILE); 294 | if (status < B_OK) 295 | return status; 296 | 297 | BMessage msg; 298 | 299 | if (fSettings->FindMessage(fName, &msg) == B_OK ) 300 | fSettings->ReplaceMessage(fName, fSaveMessage); 301 | else 302 | fSettings->AddMessage(fName, fSaveMessage); 303 | 304 | status = fSettings->Flatten(&file); 305 | if (status < B_OK) 306 | return status; 307 | 308 | return status; 309 | } 310 | 311 | 312 | status_t _Load(BMessage * settings) 313 | { 314 | BFile file; 315 | status_t status = _Open(file, B_READ_ONLY); 316 | if (status < B_OK) 317 | return status; 318 | 319 | return settings->Unflatten(&file); 320 | } 321 | 322 | 323 | void _CheckSaveNull(void) 324 | { 325 | if (fSettings == nullptr) { 326 | fSettings = new BMessage(); 327 | _Load(fSettings); 328 | } else if (fSaveMessage == nullptr) { 329 | fSaveMessage = new BMessage(); 330 | fSettings->FindMessage(fName, 0, fSaveMessage); 331 | } 332 | } 333 | 334 | void _CheckLoadNull(void) 335 | { 336 | if (fSettings == nullptr) { 337 | fSettings = new BMessage(); 338 | _Load(fSettings); 339 | } else if (fLoadMessage == nullptr) { 340 | fLoadMessage = new BMessage(); 341 | fSettings->FindMessage(fName, 0, fLoadMessage); 342 | } 343 | } 344 | 345 | 346 | BString fName; 347 | BString fLabel; 348 | BString fAppName; 349 | BMessage* fSettings; 350 | BMessage* fSaveMessage; 351 | BMessage* fLoadMessage; 352 | 353 | Debug out; 354 | 355 | }; 356 | 357 | #endif 358 | -------------------------------------------------------------------------------- /application/Timer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2012 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #ifndef TIMER_H 10 | #define TIMER_H 11 | 12 | #include 13 | #include 14 | 15 | class Timer { 16 | public: 17 | Timer(void) { 18 | 19 | } 20 | 21 | void Restart(void) { 22 | fBegin = Clock::now(); 23 | fEnd = fBegin; 24 | fIsRunning = true; 25 | } 26 | 27 | void Stop (void) { 28 | if (fIsRunning == false) 29 | return; 30 | 31 | fEnd = Clock::now(); 32 | fIsRunning = false; 33 | } 34 | 35 | double MS(void) { 36 | if (fIsRunning) { 37 | auto ms = std::chrono::duration_cast(Clock::now() - fBegin); 38 | return ms.count(); 39 | } else { 40 | auto ms = std::chrono::duration_cast(fEnd - fBegin); 41 | return ms.count(); 42 | } 43 | } 44 | 45 | double Seconds(void) { 46 | if (fIsRunning) { 47 | auto ms = std::chrono::duration_cast(Clock::now() - fBegin); 48 | return ms.count(); 49 | } else { 50 | auto ms = std::chrono::duration_cast(fEnd - fBegin); 51 | return ms.count(); 52 | } 53 | } 54 | 55 | private: 56 | 57 | typedef std::chrono::system_clock Clock; 58 | typedef std::chrono::milliseconds milliseconds; 59 | typedef std::chrono::milliseconds seconds; 60 | 61 | Clock::time_point fBegin; 62 | Clock::time_point fEnd; 63 | 64 | bool fIsRunning; 65 | }; 66 | 67 | #endif // TIMER_H 68 | -------------------------------------------------------------------------------- /application/Tools.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2012 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #ifndef TOOLS_H 10 | #define TOOLS_H 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | 31 | class Tools { 32 | public: 33 | static BString 34 | AppPath(void) 35 | { 36 | app_info info; 37 | be_app->GetAppInfo(&info); 38 | 39 | BPath path = BPath(&info.ref); 40 | path.GetParent(&path); 41 | 42 | return path.Path(); 43 | } 44 | 45 | 46 | static BString 47 | AppName(void) 48 | { 49 | app_info info; 50 | be_app->GetAppInfo(&info); 51 | 52 | BPath path = BPath(&info.ref); 53 | path.GetParent(&path); 54 | 55 | return path.Leaf(); 56 | } 57 | 58 | 59 | static BString 60 | SettingsPath(void) 61 | { 62 | BPath path; 63 | if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) 64 | return ""; 65 | 66 | path.Append(AppName().Capitalize()); 67 | create_directory(path.Path(), 0755); 68 | 69 | BString str(path.Path()); 70 | str.Append("/"); 71 | return str; 72 | } 73 | 74 | 75 | static std::vector 76 | Split(BString str, const char token, BString start = "", BString stop = "") 77 | { 78 | std::vector vec; 79 | 80 | int n1 = 0; 81 | int n2 = str.Length(); 82 | 83 | if (start != "") 84 | n1 = str.FindFirst(start, 0); 85 | 86 | if (stop != "") 87 | n2 = str.FindFirst(stop, n1 + 1); 88 | 89 | if (n1 == B_ERROR || n2 == B_ERROR) 90 | return vec; 91 | 92 | n1 = n1 + start.Length(); 93 | 94 | int n = n1; 95 | 96 | for (; n < n2; ++n) 97 | if (str[n] == token) { 98 | if (n > 0 && str[n-1] != token) { 99 | char temp[n - n1 + 1]; 100 | str.CopyInto(temp, n1, n - n1); 101 | temp[n - n1] = '\0'; 102 | vec.push_back(temp); 103 | n1 = n + 1; 104 | } else { 105 | n1 = n + 1; 106 | } 107 | } 108 | 109 | char temp[n - n1 + 1] ; 110 | str.CopyInto(temp, n1, n - n1); 111 | temp[n - n1] = '\0'; 112 | vec.push_back(temp); 113 | return vec; 114 | } 115 | 116 | 117 | static std::vector 118 | Split(unsigned int length, BString str, 119 | const char token, BString start, BString stop) 120 | { 121 | std::vector vec; 122 | 123 | int n1 = 0; 124 | int n2 = str.Length(); 125 | 126 | if (start != "") 127 | n1 = str.FindFirst(start, 0); 128 | 129 | if (stop != "") 130 | n2 = str.FindFirst(stop, n1 + 1); 131 | 132 | if (n1 == B_ERROR || n2 == B_ERROR) { 133 | vec.resize(length, ""); 134 | return vec; 135 | } 136 | 137 | n1 = n1 + start.Length(); 138 | 139 | int n = n1; 140 | 141 | for (; n < n2; ++n) 142 | if (str[n] == token) { 143 | if (n > 0 && str[n-1] != token) { 144 | char temp[n - n1 + 1]; 145 | str.CopyInto(temp, n1, n - n1); 146 | temp[n - n1] = '\0'; 147 | vec.push_back(temp); 148 | if (vec.size() == length) 149 | return vec; 150 | 151 | n1 = n + 1; 152 | } else { 153 | n1 = n + 1; 154 | } 155 | } 156 | 157 | char temp[n - n1 + 1] ; 158 | str.CopyInto(temp, n1, n - n1); 159 | temp[n - n1] = '\0'; 160 | vec.push_back(temp); 161 | vec.resize(length, ""); 162 | 163 | return vec; 164 | } 165 | 166 | 167 | static BString 168 | Find(BString str, BString searchStr) 169 | { 170 | BString result = ""; 171 | 172 | if (str.Length() == 0 || searchStr.Length() == 0) 173 | return result; 174 | 175 | int n1 = str.FindFirst(searchStr) + searchStr.Length(); 176 | int n2 = str.FindFirst(" ", n1); 177 | 178 | if (n2 == B_ERROR) 179 | n2 = str.Length(); 180 | 181 | str.CopyInto(result, n1, n2 - n1); 182 | 183 | return result; 184 | } 185 | 186 | 187 | static BBitmap* 188 | LoadBitmap(BString const& imageName, int size) 189 | { 190 | BResources* res = be_app->AppResources(); 191 | 192 | if (res == nullptr) 193 | return nullptr; 194 | 195 | size_t nbytes = 0; 196 | color_space cspace = B_RGBA32; 197 | 198 | const void* data = res->LoadResource('HVIF', imageName.String(), &nbytes); 199 | 200 | // size--; 201 | 202 | BBitmap* bitmap = new BBitmap(BRect(0, 0, size, size), cspace); 203 | 204 | if (bitmap->InitCheck() != B_OK) { 205 | delete bitmap; 206 | bitmap = nullptr; 207 | } else if (BIconUtils::GetVectorIcon((const uint8*)data, nbytes, bitmap) 208 | != B_OK) { 209 | delete bitmap; 210 | bitmap = nullptr; 211 | } 212 | 213 | res->RemoveResource(data); 214 | return bitmap; 215 | } 216 | 217 | 218 | static void 219 | ExportBitmap(BBitmap* bitmap, 220 | BString const& path, int32 const& format = B_PNG_FORMAT) 221 | { 222 | BBitmapStream stream(bitmap); 223 | BFile imageFile(path, B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); 224 | BTranslatorRoster *roster = BTranslatorRoster::Default(); 225 | roster->Translate(&stream, NULL, NULL, &imageFile, B_PNG_FORMAT); 226 | BBitmap* bmp; 227 | stream.DetachBitmap(&bmp); 228 | 229 | } 230 | 231 | 232 | static std::unique_ptr 233 | RescaleBitmap(std::unique_ptr src, int32 width, int32 height) 234 | { 235 | if (src == nullptr || src->IsValid() == false) 236 | throw "Tools::RescaleBitmap"; 237 | 238 | if (height <= 0) { 239 | if (width <= 0) 240 | return src; 241 | 242 | height = (width * src->Bounds().Height()) / src->Bounds().Width(); 243 | } else if (width <= 0) { 244 | if (height <= 0) 245 | return src; 246 | 247 | width = (height * src->Bounds().Width()) / src->Bounds().Height(); 248 | } 249 | 250 | BRect srcSize = src->Bounds(); 251 | 252 | if (height < 0) { 253 | float srcProp = srcSize.Height()/srcSize.Width(); 254 | height = (int32)(width * ceil(srcProp)); 255 | } 256 | 257 | BBitmap* res = new BBitmap(BRect(0, 0, (float)width, (float)height), 258 | src->ColorSpace()); 259 | 260 | float dx = (srcSize.Width() + 1)/(float)(width + 1); 261 | float dy = (srcSize.Height() + 1)/(float)(height + 1); 262 | uint8 bpp = (uint8)(src->BytesPerRow()/ceil(srcSize.Width())); 263 | 264 | int srcYOff = src->BytesPerRow(); 265 | int dstYOff = res->BytesPerRow(); 266 | 267 | void* dstData = res->Bits(); 268 | void* srcData = src->Bits(); 269 | 270 | for (int32 y = 0; y <= height; y++) { 271 | void* dstRow = (void*)((uintptr_t)dstData + (uintptr_t)(y * dstYOff)); 272 | void* srcRow = (void*)((uintptr_t)srcData + ((uintptr_t)(y * dy) * srcYOff)); 273 | 274 | for (int32 x = 0; x <= width; x++) 275 | memcpy((void*)((uintptr_t)dstRow + (x * bpp)), (void*)((uintptr_t)srcRow 276 | + ((uintptr_t)(x * dx) * bpp)), bpp); 277 | } 278 | 279 | std::unique_ptr bitmap(res); 280 | return bitmap; 281 | } 282 | 283 | 284 | private: 285 | Tools(void); 286 | }; 287 | 288 | #endif 289 | -------------------------------------------------------------------------------- /application/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2011 Haiku Inc. All rights reserved. 3 | * Distributed under the terms of the MIT License. 4 | * 5 | * Authors: 6 | * Ciprian Nedisan (cipri) 7 | * 8 | */ 9 | #include "MainApplication.h" 10 | 11 | int main( void ) 12 | { 13 | new MainApplication(); 14 | 15 | be_app->Run(); 16 | 17 | delete be_app; 18 | 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /documentation/help.odt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HaikuArchives/DocumentViewer/963d1176cdfe9aab945531633f01334eaac0a686/documentation/help.odt -------------------------------------------------------------------------------- /documentation/help.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HaikuArchives/DocumentViewer/963d1176cdfe9aab945531633f01334eaac0a686/documentation/help.pdf --------------------------------------------------------------------------------