void XournalView::scrollTo(size_t pageNo, double yDocument) { XOJ_CHECK_TYPE(XournalView); if (pageNo == size_t_npos || pageNo >= this->viewPagesLen) { return; } PageView* v = this->viewPages[pageNo]; Layout* layout = gtk_xournal_get_layout(this->widget); layout->ensureRectIsVisible(v->layout.getLayoutAbsoluteX(), v->layout.getLayoutAbsoluteY() + yDocument, v->getDisplayWidth(), v->getDisplayHeight()); }
static gboolean gtk_xournal_expose(GtkWidget* widget, GdkEventExpose* event) { g_return_val_if_fail(widget != NULL, FALSE); g_return_val_if_fail(GTK_IS_XOURNAL(widget), FALSE); g_return_val_if_fail(event != NULL, FALSE); GtkXournal* xournal = GTK_XOURNAL(widget); gdk_threads_enter(); cairo_t* cr = gdk_cairo_create(GTK_WIDGET(widget)->window); ArrayIterator<PageView*> it = xournal->view->pageViewIterator(); GtkAllocation alloc = { 0 }; gtk_widget_get_allocation(widget, &alloc); int lastVisibleX = alloc.width + xournal->x + 10; int lastVisibleY = alloc.height + xournal->y + 10; //+10 fix to draw the shadow int firstVisibleX = xournal->x - 10; int firstVisibleY = xournal->y - 10; while (it.hasNext()) { PageView* pv = it.next(); int px = pv->getX(); int py = pv->getY(); int pw = pv->getDisplayWidth(); int ph = pv->getDisplayHeight(); // not visible, its on the right side of the visible area if (px > lastVisibleX) { continue; } // not visible, its on the left side of the visible area if (px + pw < firstVisibleX) { continue; } // not visible, its on the bottom side of the visible area if (py > lastVisibleY) { continue; } // not visible, its on the top side of the visible area if (py + ph < firstVisibleY) { continue; } int x = px - xournal->x; int y = py - xournal->y; gtk_xournal_draw_shadow(xournal, cr, x, y, pw, ph, pv->isSelected()); cairo_save(cr); cairo_translate(cr, x, y); GdkRectangle rect = event->area; rect.x -= x; rect.y -= y; pv->paintPage(cr, &rect); cairo_restore(cr); } if (xournal->selection) { double zoom = xournal->view->getZoom(); int px = xournal->selection->getXOnView() * zoom; int py = xournal->selection->getYOnView() * zoom; // int pw = xournal->selection->getWidth() * zoom; // int ph = xournal->selection->getHeight() * zoom; // not visible, its on the right side of the visible area if (px > lastVisibleX) { printf("Warning: object on right side of visible area.\n"); } else // not visible, its on the left side of the visible area // TODO LOW PRIO this is not working correct if the zoom is small, xournal->x is never smaller than 0 // if (px + pw < firstVisibleX) { // printf("test2\n"); // } else // not visible, its on the bottom side of the visible area if (py > lastVisibleY) { printf("Warning: object below visible area.\n"); // } else // // not visible, its on the top side of the visible area // if (py + ph < firstVisibleY) { // printf("test4 %i:: %i\n", py + ph, firstVisibleY); } else { Redrawable* red = xournal->selection->getView(); cairo_translate(cr, red->getX() - xournal->x, red->getY() - xournal->y); xournal->selection->paint(cr, zoom); } } cairo_destroy(cr); gdk_threads_leave(); return true; }
/** * Check which page should be selected */ void Layout::checkSelectedPage() { GtkAllocation allocation = { 0 }; gtk_widget_get_allocation(this->view->getWidget(), &allocation); int scrollY = this->scrollVertical->getValue(); int scrollX = this->scrollHorizontal->getValue(); Control* control = this->view->getControl(); int viewHeight = allocation.height; int viewWidth = allocation.width; bool twoPages = control->getSettings()->isShowTwoPages(); if (scrollY < 1) { if (twoPages && this->view->viewPagesLen > 1 && this->view->viewPages[1]->isSelected()) { // page 2 already selected } else { control->firePageSelected(0); } return; } int mostPageNr = 0; double mostPagePercent = 0; // next four pages are not marked as invisible, // because usually you scroll forward for (int page = 0; page < this->view->viewPagesLen; page++) { PageView* p = this->view->viewPages[page]; int y = p->getY(); int x = p->getX(); int pageHeight = p->getDisplayHeight(); int pageWidth = p->getDisplayWidth(); if (y > scrollY + viewHeight) { p->setIsVisible(false); for (; page < this->view->viewPagesLen; page++) { p = this->view->viewPages[page]; p->setIsVisible(false); } break; } if (y + pageHeight >= scrollY) { int startY = 0; int endY = pageHeight; if (y <= scrollY) { startY = scrollY - y; } if (y + pageHeight > scrollY + viewHeight) { endY = pageHeight - ((y + pageHeight) - (scrollY + viewHeight)); } int startX = 0; int endX = pageWidth; if (x <= scrollX) { startX = scrollX - x; } if (x + pageWidth > scrollX + viewWidth) { endX = pageWidth - ((x + pageWidth) - (scrollX + viewWidth)); } double percent = ((double) (endY - startY)) / ((double) pageHeight); percent *= ((double) (endX - startX)) / ((double) pageWidth); if (percent > mostPagePercent) { mostPagePercent = percent; mostPageNr = page; } p->setIsVisible(true); } else { p->setIsVisible(false); } } if (twoPages && mostPageNr < this->view->viewPagesLen - 1) { int y1 = this->view->viewPages[mostPageNr]->getY(); int y2 = this->view->viewPages[mostPageNr + 1]->getY(); if (y1 != y2 || !this->view->viewPages[mostPageNr + 1]->isSelected()) { // if the second page is selected DON'T select the first page. // Only select the first page if none is selected control->firePageSelected(mostPageNr); } } else { control->firePageSelected(mostPageNr); } }
void Layout::layoutPages() { XOJ_CHECK_TYPE(Layout); int y = 0; int len = this->view->viewPagesLen; Settings* settings = this->view->getControl()->getSettings(); bool verticalSpace = settings->getAddVerticalSpace(), horizontalSpace = settings->getAddHorizontalSpace(); bool dualPage = settings->isShowTwoPages(); int size[2] = { 0, 0 }; // we need at least 2 page for dual page view if (len < 2) { dualPage = false; } // calculate maximum size for (int i = 0; i < len; i++) { PageView* v = this->view->viewPages[i]; int rId = 0; if (dualPage && i % 2 == 1) { rId = 1; } if (size[rId] < v->getDisplayWidth()) { size[rId] = v->getDisplayWidth(); } } int marginLeft = 0; int marginRight = 0; int marginTop = 0; int marginBottom = 0; y += XOURNAL_PADDING; int width = XOURNAL_PADDING + size[0]; if (dualPage) { width += XOURNAL_PADDING_BETWEEN + size[1] + XOURNAL_PADDING; } else { width += XOURNAL_PADDING; } GtkAllocation alloc; gtk_widget_get_allocation(this->view->getWidget(), &alloc); marginLeft = marginRight = (alloc.width - width) / 2; marginLeft = MAX(marginLeft, 10); marginRight = MAX(marginRight, 10); if (horizontalSpace) { marginLeft += size[0] / 2; if (dualPage) { marginRight += size[1] / 2; } else { marginRight += size[0] / 2; } } if (len > 0 && verticalSpace) { marginTop += this->view->viewPages[0]->getDisplayHeight() * 0.75; marginBottom += this->view->viewPages[len - 1]->getDisplayHeight() * 0.75; } for (int i = 0; i < len; i++) { PageView* v = this->view->viewPages[i]; int height = 0; if (dualPage) { /** * Align the left page right and the right page left, like this * (first page at right) * * [===] * [==] [=] * [===] [===] */ if (i == 0) { int x = XOURNAL_PADDING + size[0] + XOURNAL_PADDING_BETWEEN; v->layout.setX(x); v->layout.setY(y); v->layout.setMarginLeft(marginLeft); v->layout.setMarginTop(marginTop); height = v->getDisplayHeight(); } else { PageView* v2 = NULL; height = v->getDisplayHeight(); if (i + 1 < len) { i++; v2 = this->view->viewPages[i]; if (height < v2->getDisplayHeight()) { height = v2->getDisplayHeight(); } } // left page, align right int x1 = XOURNAL_PADDING + (size[0] - v->getDisplayWidth()); v->layout.setX(x1); v->layout.setY(y); v->layout.setMarginLeft(marginLeft); v->layout.setMarginTop(marginTop); // if right page available, align left if (v2 != NULL) { int x2 = XOURNAL_PADDING + size[0] + XOURNAL_PADDING_BETWEEN; v2->layout.setX(x2); v2->layout.setY(y); v2->layout.setMarginLeft(marginLeft); v2->layout.setMarginTop(marginTop); } } } else { /** * Center vertically, like this * * [=] * [===] * [===] * [=] */ int x = (size[0] - v->getDisplayWidth()) / 2 + XOURNAL_PADDING; v->layout.setX(x); v->layout.setY(y); v->layout.setMarginLeft(marginLeft); v->layout.setMarginTop(marginTop); height = v->getDisplayHeight(); } y += height; y += XOURNAL_PADDING_BETWEEN; } int height = marginTop + XOURNAL_PADDING + y + XOURNAL_PADDING + marginBottom; this->setLayoutSize(marginLeft + width + marginRight, height); this->view->pagePosition->update(this->view->viewPages, len, height); this->updateRepaintWidget(); }