diff options
Diffstat (limited to 'src/ui/documentwidget.c')
-rw-r--r-- | src/ui/documentwidget.c | 144 |
1 files changed, 142 insertions, 2 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 936c3cb7..70201d7b 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -315,6 +315,10 @@ void init_DocumentWidget(iDocumentWidget *d) { | |||
315 | init_Widget(w); | 315 | init_Widget(w); |
316 | setId_Widget(w, format_CStr("document%03d", ++docEnum_)); | 316 | setId_Widget(w, format_CStr("document%03d", ++docEnum_)); |
317 | setFlags_Widget(w, hover_WidgetFlag | noBackground_WidgetFlag, iTrue); | 317 | setFlags_Widget(w, hover_WidgetFlag | noBackground_WidgetFlag, iTrue); |
318 | if (deviceType_App() != desktop_AppDeviceType) { | ||
319 | setFlags_Widget(w, leftEdgeDraggable_WidgetFlag | rightEdgeDraggable_WidgetFlag | | ||
320 | horizontalOffset_WidgetFlag, iTrue); | ||
321 | } | ||
318 | init_PersistentDocumentState(&d->mod); | 322 | init_PersistentDocumentState(&d->mod); |
319 | d->flags = 0; | 323 | d->flags = 0; |
320 | d->phoneToolbar = NULL; | 324 | d->phoneToolbar = NULL; |
@@ -977,6 +981,9 @@ static void updateTimestampBuf_DocumentWidget_(const iDocumentWidget *d) { | |||
977 | } | 981 | } |
978 | 982 | ||
979 | static void invalidate_DocumentWidget_(iDocumentWidget *d) { | 983 | static void invalidate_DocumentWidget_(iDocumentWidget *d) { |
984 | if (flags_Widget(as_Widget(d)) & destroyPending_WidgetFlag) { | ||
985 | return; | ||
986 | } | ||
980 | invalidate_VisBuf(d->visBuf); | 987 | invalidate_VisBuf(d->visBuf); |
981 | clear_PtrSet(d->invalidRuns); | 988 | clear_PtrSet(d->invalidRuns); |
982 | } | 989 | } |
@@ -2237,6 +2244,133 @@ static iBool handlePinch_DocumentWidget_(iDocumentWidget *d, const char *cmd) { | |||
2237 | return iTrue; | 2244 | return iTrue; |
2238 | } | 2245 | } |
2239 | 2246 | ||
2247 | static void swap_DocumentWidget_(iDocumentWidget *d, iGmDocument *doc, | ||
2248 | iDocumentWidget *swapBuffersWith) { | ||
2249 | if (doc) { | ||
2250 | iAssert(isInstance_Object(doc, &Class_GmDocument)); | ||
2251 | iGmDocument *copy = ref_Object(doc); | ||
2252 | iRelease(d->doc); | ||
2253 | d->doc = copy; | ||
2254 | d->scrollY = swapBuffersWith->scrollY; | ||
2255 | updateVisible_DocumentWidget_(d); | ||
2256 | iSwap(iVisBuf *, d->visBuf, swapBuffersWith->visBuf); | ||
2257 | iSwap(iVisBufMeta *, d->visBufMeta, swapBuffersWith->visBufMeta); | ||
2258 | iSwap(iDrawBufs *, d->drawBufs, swapBuffersWith->drawBufs); | ||
2259 | invalidate_DocumentWidget_(swapBuffersWith); | ||
2260 | } | ||
2261 | } | ||
2262 | |||
2263 | static iWidget *swipeParent_DocumentWidget_(iDocumentWidget *d) { | ||
2264 | return findChild_Widget(as_Widget(d)->root->widget, "doctabs"); | ||
2265 | } | ||
2266 | |||
2267 | static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) { | ||
2268 | iWidget *w = as_Widget(d); | ||
2269 | if (equal_Command(cmd, "edgeswipe.moved")) { | ||
2270 | as_Widget(d)->offsetRef = NULL; | ||
2271 | const int side = argLabel_Command(cmd, "side"); | ||
2272 | const int offset = arg_Command(cmd); | ||
2273 | if (side == 1) { | ||
2274 | if (atOldest_History(d->mod.history)) { | ||
2275 | return iTrue; | ||
2276 | } | ||
2277 | iWidget *swipeParent = swipeParent_DocumentWidget_(d); | ||
2278 | /* The temporary "swipeIn" will display the previous page until the finger is lifted. */ | ||
2279 | iDocumentWidget *swipeIn = findChild_Widget(swipeParent, "swipein"); | ||
2280 | if (!swipeIn) { | ||
2281 | swipeIn = new_DocumentWidget(); | ||
2282 | setId_Widget(as_Widget(swipeIn), "swipein"); | ||
2283 | setFlags_Widget(as_Widget(swipeIn), | ||
2284 | disabled_WidgetFlag | refChildrenOffset_WidgetFlag | | ||
2285 | fixedPosition_WidgetFlag | fixedSize_WidgetFlag, iTrue); | ||
2286 | swipeIn->widget.rect.pos = windowToInner_Widget(swipeParent, localToWindow_Widget(w, w->rect.pos)); | ||
2287 | swipeIn->widget.rect.size = d->widget.rect.size; | ||
2288 | swipeIn->widget.offsetRef = w; | ||
2289 | iRecentUrl *recent = new_RecentUrl(); | ||
2290 | preceding_History(d->mod.history, recent); | ||
2291 | if (recent->cachedDoc) { | ||
2292 | iChangeRef(swipeIn->doc, recent->cachedDoc); | ||
2293 | updateScrollMax_DocumentWidget_(d); | ||
2294 | setValue_Anim(&swipeIn->scrollY.pos, size_GmDocument(swipeIn->doc).y * recent->normScrollY, 0); | ||
2295 | updateVisible_DocumentWidget_(swipeIn); | ||
2296 | } | ||
2297 | delete_RecentUrl(recent); | ||
2298 | addChildPos_Widget(swipeParent, iClob(swipeIn), front_WidgetAddPos); | ||
2299 | } | ||
2300 | } | ||
2301 | if (side == 2) { | ||
2302 | if (offset < -get_Window()->pixelRatio * 10) { | ||
2303 | if (!atLatest_History(d->mod.history) && | ||
2304 | ~flags_Widget(w) & dragged_WidgetFlag) { | ||
2305 | postCommand_Widget(d, "navigate.forward"); | ||
2306 | setFlags_Widget(w, dragged_WidgetFlag, iTrue); | ||
2307 | /* Set up the swipe dummy. */ | ||
2308 | iWidget *swipeParent = swipeParent_DocumentWidget_(d); | ||
2309 | iDocumentWidget *target = new_DocumentWidget(); | ||
2310 | setId_Widget(as_Widget(target), "swipeout"); | ||
2311 | /* The target takes the old document and jumps on top. */ | ||
2312 | target->widget.rect.pos = windowToInner_Widget(swipeParent, localToWindow_Widget(w, w->rect.pos)); | ||
2313 | target->widget.rect.size = d->widget.rect.size; | ||
2314 | setFlags_Widget(as_Widget(target), fixedPosition_WidgetFlag | fixedSize_WidgetFlag, iTrue); | ||
2315 | swap_DocumentWidget_(target, d->doc, d); | ||
2316 | addChildPos_Widget(swipeParent, iClob(target), front_WidgetAddPos); | ||
2317 | setFlags_Widget(as_Widget(target), refChildrenOffset_WidgetFlag, iTrue); | ||
2318 | as_Widget(target)->offsetRef = parent_Widget(w); | ||
2319 | destroy_Widget(as_Widget(target)); /* will be actually deleted after animation finishes */ | ||
2320 | } | ||
2321 | if (flags_Widget(w) & dragged_WidgetFlag) { | ||
2322 | setVisualOffset_Widget(w, width_Widget(w) + offset, 10, 0); | ||
2323 | } | ||
2324 | else { | ||
2325 | setVisualOffset_Widget(w, offset / 4, 10, 0); | ||
2326 | } | ||
2327 | } | ||
2328 | return iTrue; | ||
2329 | } | ||
2330 | } | ||
2331 | if (equal_Command(cmd, "edgeswipe.ended") && argLabel_Command(cmd, "side") == 2) { | ||
2332 | if (argLabel_Command(cmd, "abort") && flags_Widget(w) & dragged_WidgetFlag) { | ||
2333 | postCommand_Widget(d, "navigate.back"); | ||
2334 | } | ||
2335 | setFlags_Widget(w, dragged_WidgetFlag, iFalse); | ||
2336 | setVisualOffset_Widget(w, 0, 100, 0); | ||
2337 | return iTrue; | ||
2338 | } | ||
2339 | if (equal_Command(cmd, "edgeswipe.ended") && argLabel_Command(cmd, "side") == 1) { | ||
2340 | iWidget *swipeParent = swipeParent_DocumentWidget_(d); | ||
2341 | iWidget *swipeIn = findChild_Widget(swipeParent, "swipein"); | ||
2342 | if (swipeIn) { | ||
2343 | swipeIn->offsetRef = NULL; | ||
2344 | destroy_Widget(swipeIn); | ||
2345 | } | ||
2346 | } | ||
2347 | if (equal_Command(cmd, "swipe.back")) { | ||
2348 | if (atOldest_History(d->mod.history)) { | ||
2349 | setVisualOffset_Widget(w, 0, 100, 0); | ||
2350 | return iTrue; | ||
2351 | } | ||
2352 | iWidget *swipeParent = swipeParent_DocumentWidget_(d); | ||
2353 | iDocumentWidget *target = new_DocumentWidget(); | ||
2354 | setId_Widget(as_Widget(target), "swipeout"); | ||
2355 | /* The target takes the old document and jumps on top. */ | ||
2356 | target->widget.rect.pos = windowToInner_Widget(swipeParent, innerToWindow_Widget(w, zero_I2())); | ||
2357 | /* Note: `innerToWindow_Widget` does not apply visual offset. */ | ||
2358 | target->widget.rect.size = w->rect.size; | ||
2359 | setFlags_Widget(as_Widget(target), fixedPosition_WidgetFlag | fixedSize_WidgetFlag, iTrue); | ||
2360 | swap_DocumentWidget_(target, d->doc, d); | ||
2361 | addChildPos_Widget(swipeParent, iClob(target), back_WidgetAddPos); | ||
2362 | setFlags_Widget(as_Widget(d), refChildrenOffset_WidgetFlag, iTrue); | ||
2363 | as_Widget(d)->offsetRef = swipeParent; | ||
2364 | setVisualOffset_Widget(as_Widget(target), value_Anim(&w->visualOffset), 0, 0); | ||
2365 | setVisualOffset_Widget(as_Widget(target), width_Widget(target), 150, 0); | ||
2366 | destroy_Widget(as_Widget(target)); /* will be actually deleted after animation finishes */ | ||
2367 | setVisualOffset_Widget(w, 0, 0, 0); | ||
2368 | postCommand_Widget(d, "navigate.back"); | ||
2369 | return iTrue; | ||
2370 | } | ||
2371 | return iFalse; | ||
2372 | } | ||
2373 | |||
2240 | static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) { | 2374 | static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) { |
2241 | iWidget *w = as_Widget(d); | 2375 | iWidget *w = as_Widget(d); |
2242 | if (equal_Command(cmd, "document.openurls.changed")) { | 2376 | if (equal_Command(cmd, "document.openurls.changed")) { |
@@ -2842,7 +2976,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
2842 | uiHeading_ColorEscape "${heading.import.bookmarks}", | 2976 | uiHeading_ColorEscape "${heading.import.bookmarks}", |
2843 | formatCStrs_Lang("dlg.import.found.n", count), | 2977 | formatCStrs_Lang("dlg.import.found.n", count), |
2844 | (iMenuItem[]){ { "${cancel}", 0, 0, NULL }, | 2978 | (iMenuItem[]){ { "${cancel}", 0, 0, NULL }, |
2845 | { format_CStr(cstrCount_Lang("dlg.import.add.n", count), | 2979 | { format_CStr(cstrCount_Lang("dlg.import.add.n", (int) count), |
2846 | uiTextAction_ColorEscape, | 2980 | uiTextAction_ColorEscape, |
2847 | count), | 2981 | count), |
2848 | 0, | 2982 | 0, |
@@ -2901,6 +3035,10 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
2901 | else if (startsWith_CStr(cmd, "pinch.") && document_Command(cmd) == d) { | 3035 | else if (startsWith_CStr(cmd, "pinch.") && document_Command(cmd) == d) { |
2902 | return handlePinch_DocumentWidget_(d, cmd); | 3036 | return handlePinch_DocumentWidget_(d, cmd); |
2903 | } | 3037 | } |
3038 | else if ((startsWith_CStr(cmd, "edgeswipe.") || startsWith_CStr(cmd, "swipe.")) && | ||
3039 | document_App() == d) { | ||
3040 | return handleSwipe_DocumentWidget_(d, cmd); | ||
3041 | } | ||
2904 | return iFalse; | 3042 | return iFalse; |
2905 | } | 3043 | } |
2906 | 3044 | ||
@@ -4306,7 +4444,8 @@ static iBool render_DocumentWidget_(const iDocumentWidget *d, iDrawContext *ctx, | |||
4306 | /* Swap buffers around to have room available both before and after the visible region. */ | 4444 | /* Swap buffers around to have room available both before and after the visible region. */ |
4307 | allocVisBuffer_DocumentWidget_(d); | 4445 | allocVisBuffer_DocumentWidget_(d); |
4308 | reposition_VisBuf(visBuf, vis); | 4446 | reposition_VisBuf(visBuf, vis); |
4309 | /* Redraw the invalid ranges. */ { | 4447 | /* Redraw the invalid ranges. */ |
4448 | if (~flags_Widget(constAs_Widget(d)) & destroyPending_WidgetFlag) { | ||
4310 | iPaint *p = &ctx->paint; | 4449 | iPaint *p = &ctx->paint; |
4311 | init_Paint(p); | 4450 | init_Paint(p); |
4312 | iForIndices(i, visBuf->buffers) { | 4451 | iForIndices(i, visBuf->buffers) { |
@@ -4490,6 +4629,7 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) { | |||
4490 | .vis = vis, | 4629 | .vis = vis, |
4491 | .showLinkNumbers = (d->flags & showLinkNumbers_DocumentWidgetFlag) != 0, | 4630 | .showLinkNumbers = (d->flags & showLinkNumbers_DocumentWidgetFlag) != 0, |
4492 | }; | 4631 | }; |
4632 | init_Paint(&ctx.paint); | ||
4493 | render_DocumentWidget_(d, &ctx, iFalse /* just the mandatory parts */); | 4633 | render_DocumentWidget_(d, &ctx, iFalse /* just the mandatory parts */); |
4494 | setClip_Paint(&ctx.paint, bounds); | 4634 | setClip_Paint(&ctx.paint, bounds); |
4495 | int yTop = docBounds.pos.y - pos_SmoothScroll(&d->scrollY); | 4635 | int yTop = docBounds.pos.y - pos_SmoothScroll(&d->scrollY); |