4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | *
10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.infomaniak.lib.pdfview.exception; 17 | 18 | @Deprecated 19 | public class FileNotFoundException extends RuntimeException { 20 | 21 | public FileNotFoundException(String detailMessage) { 22 | super(detailMessage); 23 | } 24 | 25 | public FileNotFoundException(String detailMessage, Throwable throwable) { 26 | super(detailMessage, throwable); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/exception/PageRenderingException.java: -------------------------------------------------------------------------------- 1 | package com.infomaniak.lib.pdfview.exception; 2 | 3 | public class PageRenderingException extends Exception { 4 | private final int page; 5 | 6 | public PageRenderingException(int page, Throwable cause) { 7 | super(cause); 8 | this.page = page; 9 | } 10 | 11 | public int getPage() { 12 | return page; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/link/DefaultLinkHandler.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Bartosz Schiller 3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.infomaniak.lib.pdfview.link; 17 | 18 | import android.content.Context; 19 | import android.content.Intent; 20 | import android.net.Uri; 21 | import android.util.Log; 22 | 23 | import com.infomaniak.lib.pdfview.PDFView; 24 | import com.infomaniak.lib.pdfview.model.LinkTapEvent; 25 | 26 | public class DefaultLinkHandler implements LinkHandler { 27 | 28 | private static final String TAG = DefaultLinkHandler.class.getSimpleName(); 29 | 30 | private PDFView pdfView; 31 | 32 | public DefaultLinkHandler(PDFView pdfView) { 33 | this.pdfView = pdfView; 34 | } 35 | 36 | @Override 37 | public void handleLinkEvent(LinkTapEvent event) { 38 | String uri = event.getLink().getUri(); 39 | Integer page = event.getLink().getDestPageIdx(); 40 | if (uri != null && !uri.isEmpty()) { 41 | handleUri(uri); 42 | } else if (page != null) { 43 | handlePage(page); 44 | } 45 | } 46 | 47 | private void handleUri(String uri) { 48 | Uri parsedUri = Uri.parse(uri); 49 | Intent intent = new Intent(Intent.ACTION_VIEW, parsedUri); 50 | Context context = pdfView.getContext(); 51 | if (intent.resolveActivity(context.getPackageManager()) != null) { 52 | context.startActivity(intent); 53 | } else { 54 | Log.w(TAG, "No activity found for URI: " + uri); 55 | } 56 | } 57 | 58 | private void handlePage(int page) { 59 | pdfView.jumpTo(page); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/link/LinkHandler.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Bartosz Schiller 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.infomaniak.lib.pdfview.link; 17 | 18 | import com.infomaniak.lib.pdfview.model.LinkTapEvent; 19 | 20 | public interface LinkHandler { 21 | 22 | /** 23 | * Called when link was tapped by user 24 | * 25 | * @param event current event 26 | */ 27 | void handleLinkEvent(LinkTapEvent event); 28 | } 29 | -------------------------------------------------------------------------------- /android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/listener/Callbacks.java: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Infomaniak android-pdf-viewer 4 | * Copyright (C) 2024 Infomaniak Network SA 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | *
10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.infomaniak.lib.pdfview.listener; 17 | 18 | import android.graphics.Canvas; 19 | 20 | /** 21 | * This interface allows an extern class to draw 22 | * something on the PDFView canvas, above all images. 23 | */ 24 | public interface OnDrawListener { 25 | 26 | /** 27 | * This method is called when the PDFView is 28 | * drawing its view. 29 | *
30 | * The page is starting at (0,0) 31 | * 32 | * @param canvas The canvas on which to draw things. 33 | * @param pageWidth The width of the current page. 34 | * @param pageHeight The height of the current page. 35 | * @param displayedPage The current page index 36 | */ 37 | void onLayerDrawn(Canvas canvas, float pageWidth, float pageHeight, int displayedPage); 38 | } 39 | -------------------------------------------------------------------------------- /android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/listener/OnErrorListener.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Bartosz Schiller 3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | *
10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.infomaniak.lib.pdfview.listener; 17 | 18 | public interface OnErrorListener { 19 | 20 | /** 21 | * Called if error occurred while opening PDF 22 | * 23 | * @param t Throwable with error 24 | */ 25 | void onError(Throwable t); 26 | } 27 | -------------------------------------------------------------------------------- /android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/listener/OnLoadCompleteListener.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Bartosz Schiller 3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | *
10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.infomaniak.lib.pdfview.listener; 17 | 18 | /** 19 | * Implement this interface to receive events from PDFView 20 | * when loading is complete. 21 | */ 22 | public interface OnLoadCompleteListener { 23 | 24 | /** 25 | * Called when the PDF is loaded 26 | * 27 | * @param nbPages the number of pages in this PDF file 28 | */ 29 | void loadComplete(int nbPages); 30 | } 31 | -------------------------------------------------------------------------------- /android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/listener/OnLongPressListener.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Bartosz Schiller 3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | *
10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.infomaniak.lib.pdfview.listener; 17 | 18 | import android.view.MotionEvent; 19 | 20 | /** 21 | * Implement this interface to receive events from PDFView 22 | * when view has been long pressed 23 | */ 24 | public interface OnLongPressListener { 25 | 26 | /** 27 | * Called when the user has a long tap gesture, before processing scroll handle toggling 28 | * 29 | * @param e MotionEvent that registered as a confirmed long press 30 | */ 31 | void onLongPress(MotionEvent e); 32 | } 33 | -------------------------------------------------------------------------------- /android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/listener/OnPageChangeListener.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Bartosz Schiller 3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | *
10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.infomaniak.lib.pdfview.listener; 17 | 18 | /** 19 | * Implements this interface to receive events from PDFView 20 | * when a page has changed through swipe 21 | */ 22 | public interface OnPageChangeListener { 23 | 24 | /** 25 | * Called when the user use swipe to change page 26 | * 27 | * @param page the new page displayed, starting from 0 28 | * @param pageCount the total page count 29 | */ 30 | void onPageChanged(int page, int pageCount); 31 | 32 | } 33 | -------------------------------------------------------------------------------- /android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/listener/OnPageErrorListener.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 Bartosz Schiller 3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | *
10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.infomaniak.lib.pdfview.listener; 17 | 18 | public interface OnPageErrorListener { 19 | 20 | /** 21 | * Called if error occurred while loading PDF page 22 | * 23 | * @param t Throwable with error 24 | */ 25 | void onPageError(int page, Throwable t); 26 | } 27 | -------------------------------------------------------------------------------- /android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/listener/OnPageScrollListener.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016 Bartosz Schiller 3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.infomaniak.lib.pdfview.listener;
17 |
18 | /**
19 | * Implements this interface to receive events from PDFView
20 | * when a page has been scrolled
21 | */
22 | public interface OnPageScrollListener {
23 |
24 | /**
25 | * Called on every move while scrolling
26 | *
27 | * @param page current page index
28 | * @param positionOffset see {@link com.infomaniak.lib.pdfview.PDFView#getPositionOffset()}
29 | */
30 | void onPageScrolled(int page, float positionOffset);
31 | }
32 |
--------------------------------------------------------------------------------
/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/listener/OnReadyForPrintingListener.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * Infomaniak android-pdf-viewer
4 | * Copyright (C) 2024 Infomaniak Network SA
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.infomaniak.lib.pdfview.listener;
17 |
18 | public interface OnRenderListener {
19 |
20 | /**
21 | * Called only once, when document is rendered
22 | *
23 | * @param nbPages number of pages
24 | */
25 | void onInitiallyRendered(int nbPages);
26 | }
27 |
--------------------------------------------------------------------------------
/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/listener/OnTapListener.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Bartosz Schiller
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.infomaniak.lib.pdfview.listener;
17 |
18 | import android.view.MotionEvent;
19 |
20 | /**
21 | * Implement this interface to receive events from PDFView
22 | * when view has been touched
23 | */
24 | public interface OnTapListener {
25 |
26 | /**
27 | * Called when the user has a tap gesture, before processing scroll handle toggling
28 | *
29 | * @param e MotionEvent that registered as a confirmed single tap
30 | * @return true if the single tap was handled, false to toggle scroll handle
31 | */
32 | boolean onTap(MotionEvent e);
33 | }
34 |
--------------------------------------------------------------------------------
/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/model/LinkTapEvent.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2016 Bartosz Schiller
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.infomaniak.lib.pdfview.model;
17 |
18 | import android.graphics.RectF;
19 |
20 | import com.shockwave.pdfium.PdfDocument;
21 |
22 | public class LinkTapEvent {
23 |
24 | private float originalX;
25 | private float originalY;
26 | private float documentX;
27 | private float documentY;
28 | private RectF mappedLinkRect;
29 | private PdfDocument.Link link;
30 |
31 | public LinkTapEvent(
32 | float originalX,
33 | float originalY,
34 | float documentX,
35 | float documentY,
36 | RectF mappedLinkRect,
37 | PdfDocument.Link link
38 | ) {
39 | this.originalX = originalX;
40 | this.originalY = originalY;
41 | this.documentX = documentX;
42 | this.documentY = documentY;
43 | this.mappedLinkRect = mappedLinkRect;
44 | this.link = link;
45 | }
46 |
47 | public float getOriginalX() {
48 | return originalX;
49 | }
50 |
51 | public float getOriginalY() {
52 | return originalY;
53 | }
54 |
55 | public float getDocumentX() {
56 | return documentX;
57 | }
58 |
59 | public float getDocumentY() {
60 | return documentY;
61 | }
62 |
63 | public RectF getMappedLinkRect() {
64 | return mappedLinkRect;
65 | }
66 |
67 | public PdfDocument.Link getLink() {
68 | return link;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/model/PagePart.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2016 Bartosz Schiller
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.infomaniak.lib.pdfview.model;
17 |
18 | import android.graphics.Bitmap;
19 | import android.graphics.RectF;
20 |
21 | public class PagePart {
22 |
23 | private int page;
24 |
25 | private Bitmap renderedBitmap;
26 |
27 | private RectF pageRelativeBounds;
28 |
29 | private boolean thumbnail;
30 |
31 | private int cacheOrder;
32 |
33 | public PagePart(int page, Bitmap renderedBitmap, RectF pageRelativeBounds, boolean thumbnail, int cacheOrder) {
34 | super();
35 | this.page = page;
36 | this.renderedBitmap = renderedBitmap;
37 | this.pageRelativeBounds = pageRelativeBounds;
38 | this.thumbnail = thumbnail;
39 | this.cacheOrder = cacheOrder;
40 | }
41 |
42 | public int getCacheOrder() {
43 | return cacheOrder;
44 | }
45 |
46 | public void setCacheOrder(int cacheOrder) {
47 | this.cacheOrder = cacheOrder;
48 | }
49 |
50 | public int getPage() {
51 | return page;
52 | }
53 |
54 | public Bitmap getRenderedBitmap() {
55 | return renderedBitmap;
56 | }
57 |
58 | public RectF getPageRelativeBounds() {
59 | return pageRelativeBounds;
60 | }
61 |
62 | public boolean isThumbnail() {
63 | return thumbnail;
64 | }
65 |
66 | @Override
67 | public boolean equals(Object obj) {
68 | if (!(obj instanceof PagePart)) {
69 | return false;
70 | }
71 |
72 | PagePart part = (PagePart) obj;
73 | return part.getPage() == page
74 | && part.getPageRelativeBounds().left == pageRelativeBounds.left
75 | && part.getPageRelativeBounds().right == pageRelativeBounds.right
76 | && part.getPageRelativeBounds().top == pageRelativeBounds.top
77 | && part.getPageRelativeBounds().bottom == pageRelativeBounds.bottom;
78 | }
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/scroll/DefaultScrollHandle.java:
--------------------------------------------------------------------------------
1 | package com.infomaniak.lib.pdfview.scroll;
2 |
3 | import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
4 |
5 | import android.content.Context;
6 | import android.graphics.drawable.Drawable;
7 | import android.os.Handler;
8 | import android.os.Looper;
9 | import android.util.TypedValue;
10 | import android.view.LayoutInflater;
11 | import android.view.MotionEvent;
12 | import android.view.View;
13 | import android.widget.RelativeLayout;
14 | import android.widget.TextView;
15 |
16 | import androidx.core.content.ContextCompat;
17 |
18 | import com.infomaniak.lib.pdfview.PDFView;
19 | import com.infomaniak.lib.pdfview.R;
20 | import com.infomaniak.lib.pdfview.util.TouchUtils;
21 | import com.infomaniak.lib.pdfview.util.Util;
22 |
23 | public class DefaultScrollHandle extends RelativeLayout implements ScrollHandle {
24 |
25 | private static final int HANDLE_WIDTH = 65;
26 | private static final int HANDLE_HEIGHT = 40;
27 | private static final int NO_ALIGN = -1;
28 | private static final int TOUCH_POINTER_COUNT = 1;
29 |
30 | private final Handler handler = new Handler(Looper.getMainLooper());
31 | private final boolean inverted;
32 | private final Runnable hidePageScrollerRunnable = this::hide;
33 | protected TextView pageIndicator;
34 | protected Context context;
35 | private float relativeHandlerMiddle = 0f;
36 | private PDFView pdfView;
37 | private float currentPos;
38 | private Drawable handleBackgroundDrawable;
39 | private View handleView;
40 | private int handleAlign;
41 | private int handleWidth = HANDLE_WIDTH;
42 | private int handleHeight = HANDLE_HEIGHT;
43 | private int handlePaddingLeft = 0;
44 | private int handlePaddingTop = 0;
45 | private int handlePaddingRight = 0;
46 | private int handlePaddingBottom = 0;
47 |
48 | private int hideHandleDelayMillis = 1000;
49 |
50 | private boolean hasStartedDragging = false;
51 | private int textColorResId = -1;
52 | private int textSize = -1;
53 |
54 | public DefaultScrollHandle(Context context) {
55 | this(context, false);
56 | }
57 |
58 | public DefaultScrollHandle(Context context, boolean inverted) {
59 | super(context);
60 | this.context = context;
61 | this.inverted = inverted;
62 | }
63 |
64 | @Override
65 | public void setupLayout(PDFView pdfView) {
66 | setHandleRelativePosition(pdfView);
67 | setHandleView();
68 | pdfView.addView(this);
69 | this.pdfView = pdfView;
70 | }
71 |
72 | private void setHandleRelativePosition(PDFView pdfView) {
73 | // determine handler position, default is right (when scrolling vertically) or bottom (when scrolling horizontally)
74 | if (pdfView.isSwipeVertical()) {
75 | handleAlign = inverted ? ALIGN_PARENT_LEFT : ALIGN_PARENT_RIGHT;
76 | } else {
77 | int tempWidth = handleWidth;
78 | handleWidth = handleHeight;
79 | handleHeight = tempWidth;
80 | handleAlign = inverted ? ALIGN_PARENT_TOP : ALIGN_PARENT_BOTTOM;
81 | }
82 | }
83 |
84 | private void setHandleView() {
85 | if (handleView != null) {
86 | initViewWithCustomView();
87 | } else {
88 | initDefaultView(handleBackgroundDrawable);
89 | }
90 |
91 | setVisibility(INVISIBLE);
92 | if (pageIndicator != null) {
93 | if (textColorResId != -1) pageIndicator.setTextColor(textColorResId);
94 | if (textSize != -1) pageIndicator.setTextSize(TypedValue.COMPLEX_UNIT_DIP, textSize);
95 | }
96 | }
97 |
98 | private void initDefaultView(Drawable drawable) {
99 | LayoutInflater layoutInflater = LayoutInflater.from(context);
100 | View view = layoutInflater.inflate(R.layout.default_handle, null);
101 | pageIndicator = view.findViewById(R.id.pageIndicator);
102 | pageIndicator.setBackground(drawable != null ? drawable : getDefaultHandleBackgroundDrawable());
103 | addView(view, getCustomViewLayoutParams());
104 | setRootLayoutParams();
105 | }
106 |
107 | private LayoutParams getCustomViewLayoutParams() {
108 | return getLayoutParams(
109 | Util.getDP(context, handleWidth),
110 | Util.getDP(context, handleHeight),
111 | NO_ALIGN,
112 | true
113 | );
114 | }
115 |
116 | private void initViewWithCustomView() {
117 | if (handleView.getParent() != null) {
118 | removeView(handleView);
119 | }
120 | addView(handleView, getCustomViewLayoutParams());
121 | setRootLayoutParams();
122 | }
123 |
124 | private Drawable getDefaultHandleBackgroundDrawable() {
125 | int drawableResId = switch (handleAlign) {
126 | case ALIGN_PARENT_LEFT -> R.drawable.default_scroll_handle_left;
127 | case ALIGN_PARENT_RIGHT -> R.drawable.default_scroll_handle_right;
128 | case ALIGN_PARENT_TOP -> R.drawable.default_scroll_handle_top;
129 | default -> R.drawable.default_scroll_handle_bottom;
130 | };
131 | return getDrawable(drawableResId);
132 | }
133 |
134 | private LayoutParams getLayoutParams(int width, int height, int align, boolean withPadding) {
135 | LayoutParams layoutParams = new LayoutParams(width, height);
136 | if (align != NO_ALIGN) layoutParams.addRule(align);
137 |
138 | if (withPadding) {
139 | layoutParams.setMargins(
140 | Util.getDP(context, handlePaddingLeft),
141 | Util.getDP(context, handlePaddingTop),
142 | Util.getDP(context, handlePaddingRight),
143 | Util.getDP(context, handlePaddingBottom)
144 | );
145 | }
146 |
147 | return layoutParams;
148 | }
149 |
150 | private void setRootLayoutParams() {
151 | setLayoutParams(getLayoutParams(WRAP_CONTENT, WRAP_CONTENT, handleAlign, false));
152 | }
153 |
154 | private Drawable getDrawable(int resDrawable) {
155 | return ContextCompat.getDrawable(context, resDrawable);
156 | }
157 |
158 | @Override
159 | public void destroyLayout() {
160 | pdfView.removeView(this);
161 | }
162 |
163 | @Override
164 | public void setScroll(float position) {
165 | if (!shown()) {
166 | show();
167 | } else {
168 | handler.removeCallbacks(hidePageScrollerRunnable);
169 | }
170 | if (pdfView != null) {
171 | setPosition((pdfView.isSwipeVertical() ? pdfView.getHeight() : pdfView.getWidth()) * position);
172 | }
173 | }
174 |
175 | private void setPosition(float pos) {
176 | if (Float.isInfinite(pos) || Float.isNaN(pos)) {
177 | return;
178 | }
179 | float pdfViewSize;
180 | int handleSize;
181 | if (pdfView.isSwipeVertical()) {
182 | pdfViewSize = pdfView.getHeight();
183 | handleSize = handleHeight;
184 | } else {
185 | pdfViewSize = pdfView.getWidth();
186 | handleSize = handleWidth;
187 | }
188 | pos -= relativeHandlerMiddle;
189 |
190 | float maxBound = pdfViewSize - Util.getDP(context, handleSize) - getPaddings();
191 | if (pos < 0) {
192 | pos = 0;
193 | } else if (pos > maxBound) {
194 | pos = maxBound;
195 | }
196 |
197 | if (pdfView.isSwipeVertical()) {
198 | setY(pos);
199 | } else {
200 | setX(pos);
201 | }
202 |
203 | calculateMiddle();
204 | invalidate();
205 | }
206 |
207 | private int getPaddings() {
208 | int paddings = switch (handleAlign) {
209 | case ALIGN_PARENT_LEFT, ALIGN_PARENT_RIGHT -> handlePaddingTop + handlePaddingBottom;
210 | case ALIGN_PARENT_TOP, ALIGN_PARENT_BOTTOM -> handlePaddingLeft + handlePaddingRight;
211 | default -> 0;
212 | };
213 | return Util.getDP(context, paddings);
214 | }
215 |
216 | private void calculateMiddle() {
217 | float pos;
218 | float viewSize;
219 | float pdfViewSize;
220 | if (pdfView.isSwipeVertical()) {
221 | pos = getY();
222 | viewSize = getHeight();
223 | pdfViewSize = pdfView.getHeight();
224 | } else {
225 | pos = getX();
226 | viewSize = getWidth();
227 | pdfViewSize = pdfView.getWidth();
228 | }
229 | relativeHandlerMiddle = ((pos + relativeHandlerMiddle) / pdfViewSize) * viewSize;
230 | }
231 |
232 | @Override
233 | public void hideDelayed() {
234 | handler.postDelayed(hidePageScrollerRunnable, hideHandleDelayMillis);
235 | }
236 |
237 | @Override
238 | public void setPageNum(int pageNum) {
239 | String text = String.valueOf(pageNum);
240 | if (pageIndicator != null && !pageIndicator.getText().equals(text)) {
241 | pageIndicator.setText(text);
242 | }
243 | }
244 |
245 | @Override
246 | public boolean shown() {
247 | return getVisibility() == VISIBLE;
248 | }
249 |
250 | @Override
251 | public void show() {
252 | setVisibility(VISIBLE);
253 | }
254 |
255 | @Override
256 | public void hide() {
257 | setVisibility(INVISIBLE);
258 | }
259 |
260 | /**
261 | * @param color color of the text handle
262 | */
263 | public void setTextColor(int color) {
264 | textColorResId = color;
265 | }
266 |
267 | /**
268 | * @param size text size in dp
269 | */
270 | public void setTextSize(int size) {
271 | textSize = size;
272 | }
273 |
274 | /**
275 | * @param handleBackgroundDrawable drawable to set as a background
276 | */
277 | public void setPageHandleBackground(Drawable handleBackgroundDrawable) {
278 | this.handleBackgroundDrawable = handleBackgroundDrawable;
279 | }
280 |
281 | /**
282 | * Use a custom view as the handle. if you want to have the page indicator,
283 | * provide the pageIndicator parameter.
284 | *
285 | * @param handleView view to set as the handle
286 | * @param pageIndicator TextView to use as the page indicator
287 | */
288 | public void setPageHandleView(View handleView, TextView pageIndicator) {
289 | this.handleView = handleView;
290 | this.pageIndicator = pageIndicator;
291 | }
292 |
293 | /**
294 | * @param handleWidth width of the handle
295 | * @param handleHeight width of the handle
296 | */
297 | public void setHandleSize(int handleWidth, int handleHeight) {
298 | this.handleWidth = handleWidth;
299 | this.handleHeight = handleHeight;
300 | }
301 |
302 | /**
303 | * @param paddingLeft left padding of the handle
304 | * @param paddingTop top padding of the handle
305 | * @param paddingRight right padding of the handle
306 | * @param paddingBottom bottom padding of the handle
307 | */
308 | public void setHandlePaddings(int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) {
309 | handlePaddingLeft = paddingLeft;
310 | handlePaddingTop = paddingTop;
311 | handlePaddingRight = paddingRight;
312 | handlePaddingBottom = paddingBottom;
313 | }
314 |
315 | /**
316 | * @param hideHandleDelayMillis delay in milliseconds to hide the handle after scrolling the PDF
317 | */
318 | public void setHideHandleDelay(int hideHandleDelayMillis) {
319 | this.hideHandleDelayMillis = hideHandleDelayMillis;
320 | }
321 |
322 | private boolean isPDFViewReady() {
323 | return pdfView != null && pdfView.getPageCount() > 0 && !pdfView.documentFitsView();
324 | }
325 |
326 | private View getTouchedView(MotionEvent event) {
327 | int x = Math.round(event.getX());
328 | int y = Math.round(event.getY());
329 | for (int i = 0; i < getChildCount(); i++) {
330 | View child = getChildAt(i);
331 | if (x > child.getLeft() && x < child.getRight() && y > child.getTop() && y < child.getBottom()) {
332 | return child;
333 | }
334 | }
335 | return null;
336 | }
337 |
338 | private boolean shouldIgnoreTouch(MotionEvent event) {
339 | View touchedView = getTouchedView(event);
340 | if (hasStartedDragging) {
341 | return false;
342 | } else if (touchedView != null) {
343 | Object tag = touchedView.getTag();
344 | return tag != null && !tag.toString().equals("rootHandle");
345 | }
346 | return true;
347 | }
348 |
349 | @Override
350 | public boolean onTouchEvent(MotionEvent event) {
351 | if (!isPDFViewReady() || shouldIgnoreTouch(event)) {
352 | return super.onTouchEvent(event);
353 | }
354 |
355 | hasStartedDragging = true;
356 |
357 | TouchUtils.handleTouchPriority(event, this, TOUCH_POINTER_COUNT, false, pdfView.isZooming());
358 | switch (event.getAction()) {
359 | case MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_DOWN -> {
360 | pdfView.stopFling();
361 | handler.removeCallbacks(hidePageScrollerRunnable);
362 | if (pdfView.isSwipeVertical()) {
363 | currentPos = event.getRawY() - getY();
364 | } else {
365 | currentPos = event.getRawX() - getX();
366 | }
367 | return true;
368 | }
369 | case MotionEvent.ACTION_MOVE -> {
370 | if (pdfView.isSwipeVertical()) {
371 | setPosition(event.getRawY() - currentPos + relativeHandlerMiddle);
372 | pdfView.setPositionOffset(relativeHandlerMiddle / getHeight(), false);
373 | } else {
374 | setPosition(event.getRawX() - currentPos + relativeHandlerMiddle);
375 | pdfView.setPositionOffset(relativeHandlerMiddle / getWidth(), false);
376 | }
377 | return true;
378 | }
379 | case MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP -> {
380 | hideDelayed();
381 | pdfView.performPageSnap();
382 | hasStartedDragging = false;
383 | return true;
384 | }
385 | default -> {
386 | return super.onTouchEvent(event);
387 | }
388 | }
389 | }
390 | }
391 |
--------------------------------------------------------------------------------
/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/scroll/ScrollHandle.java:
--------------------------------------------------------------------------------
1 | package com.infomaniak.lib.pdfview.scroll;
2 |
3 | import com.infomaniak.lib.pdfview.PDFView;
4 |
5 | public interface ScrollHandle {
6 |
7 | /**
8 | * Used to move the handle, called internally by PDFView
9 | *
10 | * @param position current scroll ratio between 0 and 1
11 | */
12 | void setScroll(float position);
13 |
14 | /**
15 | * Method called by PDFView after setting scroll handle.
16 | * Do not call this method manually.
17 | * For usage sample see {@link DefaultScrollHandle}
18 | *
19 | * @param pdfView PDFView instance
20 | */
21 | void setupLayout(PDFView pdfView);
22 |
23 | /**
24 | * Method called by PDFView when handle should be removed from layout
25 | * Do not call this method manually.
26 | */
27 | void destroyLayout();
28 |
29 | /**
30 | * Set page number displayed on handle
31 | *
32 | * @param pageNum page number
33 | */
34 | void setPageNum(int pageNum);
35 |
36 | /**
37 | * Get handle visibility
38 | *
39 | * @return true if handle is visible, false otherwise
40 | */
41 | boolean shown();
42 |
43 | /**
44 | * Show handle
45 | */
46 | void show();
47 |
48 | /**
49 | * Hide handle immediately
50 | */
51 | void hide();
52 |
53 | /**
54 | * Hide handle after some time (defined by implementation)
55 | */
56 | void hideDelayed();
57 | }
58 |
--------------------------------------------------------------------------------
/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/source/AssetSource.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Bartosz Schiller.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.infomaniak.lib.pdfview.source;
17 |
18 | import android.content.Context;
19 | import android.os.ParcelFileDescriptor;
20 |
21 | import com.infomaniak.lib.pdfview.util.FileUtils;
22 | import com.shockwave.pdfium.PdfDocument;
23 | import com.shockwave.pdfium.PdfiumCore;
24 |
25 | import java.io.File;
26 | import java.io.IOException;
27 |
28 | public class AssetSource implements DocumentSource {
29 |
30 | private final String assetName;
31 |
32 | public AssetSource(String assetName) {
33 | this.assetName = assetName;
34 | }
35 |
36 | @Override
37 | public PdfDocument createDocument(Context context, PdfiumCore core, String password) throws IOException {
38 | File f = FileUtils.fileFromAsset(context, assetName);
39 | ParcelFileDescriptor pfd = ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
40 | return core.newDocument(pfd, password);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/source/ByteArraySource.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Bartosz Schiller.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.infomaniak.lib.pdfview.source;
17 |
18 | import android.content.Context;
19 |
20 | import com.shockwave.pdfium.PdfDocument;
21 | import com.shockwave.pdfium.PdfiumCore;
22 |
23 | import java.io.IOException;
24 |
25 | public class ByteArraySource implements DocumentSource {
26 |
27 | private byte[] data;
28 |
29 | public ByteArraySource(byte[] data) {
30 | this.data = data;
31 | }
32 |
33 | @Override
34 | public PdfDocument createDocument(Context context, PdfiumCore core, String password) throws IOException {
35 | return core.newDocument(data, password);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/source/DocumentSource.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Bartosz Schiller.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.infomaniak.lib.pdfview.source;
17 |
18 | import android.content.Context;
19 |
20 | import com.shockwave.pdfium.PdfDocument;
21 | import com.shockwave.pdfium.PdfiumCore;
22 |
23 | import java.io.IOException;
24 |
25 | public interface DocumentSource {
26 | PdfDocument createDocument(Context context, PdfiumCore core, String password) throws IOException;
27 | }
28 |
--------------------------------------------------------------------------------
/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/source/FileSource.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Bartosz Schiller.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.infomaniak.lib.pdfview.source;
17 |
18 | import android.content.Context;
19 | import android.os.ParcelFileDescriptor;
20 |
21 | import com.shockwave.pdfium.PdfDocument;
22 | import com.shockwave.pdfium.PdfiumCore;
23 |
24 | import java.io.File;
25 | import java.io.IOException;
26 |
27 | public class FileSource implements DocumentSource {
28 |
29 | private File file;
30 |
31 | public FileSource(File file) {
32 | this.file = file;
33 | }
34 |
35 | @Override
36 | public PdfDocument createDocument(Context context, PdfiumCore core, String password) throws IOException {
37 | ParcelFileDescriptor pfd = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
38 | return core.newDocument(pfd, password);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/source/InputStreamSource.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Bartosz Schiller.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.infomaniak.lib.pdfview.source;
17 |
18 | import android.content.Context;
19 |
20 | import com.infomaniak.lib.pdfview.util.Util;
21 | import com.shockwave.pdfium.PdfDocument;
22 | import com.shockwave.pdfium.PdfiumCore;
23 |
24 | import java.io.IOException;
25 | import java.io.InputStream;
26 |
27 | public class InputStreamSource implements DocumentSource {
28 |
29 | private InputStream inputStream;
30 |
31 | public InputStreamSource(InputStream inputStream) {
32 | this.inputStream = inputStream;
33 | }
34 |
35 | @Override
36 | public PdfDocument createDocument(Context context, PdfiumCore core, String password) throws IOException {
37 | return core.newDocument(Util.toByteArray(inputStream), password);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/source/UriSource.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Bartosz Schiller.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.infomaniak.lib.pdfview.source;
17 |
18 | import android.content.Context;
19 | import android.net.Uri;
20 | import android.os.ParcelFileDescriptor;
21 |
22 | import com.shockwave.pdfium.PdfDocument;
23 | import com.shockwave.pdfium.PdfiumCore;
24 |
25 | import java.io.IOException;
26 |
27 | public class UriSource implements DocumentSource {
28 |
29 | private Uri uri;
30 |
31 | public UriSource(Uri uri) {
32 | this.uri = uri;
33 | }
34 |
35 | public Uri getUri() {
36 | return uri;
37 | }
38 |
39 | @Override
40 | public PdfDocument createDocument(Context context, PdfiumCore core, String password) throws IOException {
41 | ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uri, "r");
42 | return core.newDocument(pfd, password);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/util/ArrayUtils.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2016 Bartosz Schiller
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.infomaniak.lib.pdfview.util;
17 |
18 | import java.util.ArrayList;
19 | import java.util.List;
20 |
21 | public class ArrayUtils {
22 |
23 | private ArrayUtils() {
24 | // Prevents instantiation
25 | }
26 |
27 | /**
28 | * Transforms (0,1,2,2,3) to (0,1,2,3)
29 | */
30 | public static int[] deleteDuplicatedPages(int[] pages) {
31 | List