Adds back/forward buttons to page menu
This commit is contained in:
@@ -203,6 +203,7 @@ class BrowserViewController: UIViewController, WKNavigationDelegate, WKUIDelegat
|
|||||||
let label = documentControls.fontSizeAdjustView.labelView
|
let label = documentControls.fontSizeAdjustView.labelView
|
||||||
label.text = numberFormatter.string(for: tab.webView._viewScale)
|
label.text = numberFormatter.string(for: tab.webView._viewScale)
|
||||||
|
|
||||||
|
// Font size adjust
|
||||||
documentControls.fontSizeAdjustView.decreaseSizeButton.addAction(UIAction(handler: { [unowned self] sender in
|
documentControls.fontSizeAdjustView.decreaseSizeButton.addAction(UIAction(handler: { [unowned self] sender in
|
||||||
self.decreaseSize(sender)
|
self.decreaseSize(sender)
|
||||||
label.text = numberFormatter.string(for: tab.webView._viewScale)
|
label.text = numberFormatter.string(for: tab.webView._viewScale)
|
||||||
@@ -213,11 +214,31 @@ class BrowserViewController: UIViewController, WKNavigationDelegate, WKUIDelegat
|
|||||||
label.text = numberFormatter.string(for: tab.webView._viewScale)
|
label.text = numberFormatter.string(for: tab.webView._viewScale)
|
||||||
}), for: .touchUpInside)
|
}), for: .touchUpInside)
|
||||||
|
|
||||||
|
// Find on page
|
||||||
documentControls.findOnPageControlView.addAction(UIAction(handler: { [unowned self] _ in
|
documentControls.findOnPageControlView.addAction(UIAction(handler: { [unowned self] _ in
|
||||||
documentControls.dismiss(animated: true, completion: nil)
|
documentControls.dismiss(animated: true, completion: nil)
|
||||||
browserView.setFindOnPageVisible(true, animated: true)
|
browserView.setFindOnPageVisible(true, animated: true)
|
||||||
}), for: .touchUpInside)
|
}), for: .touchUpInside)
|
||||||
|
|
||||||
|
// Navigation controls
|
||||||
|
documentControls.navigationControlView.backButton.isEnabled = webView.canGoBack
|
||||||
|
documentControls.navigationControlView.backButton.addAction(UIAction() { [unowned self] _ in
|
||||||
|
webView.goBack()
|
||||||
|
}, for: .touchUpInside)
|
||||||
|
|
||||||
|
documentControls.observations.append(webView.observe(\.canGoBack, changeHandler: { (_, _) in
|
||||||
|
documentControls.navigationControlView.backButton.isEnabled = webView.canGoBack
|
||||||
|
}))
|
||||||
|
|
||||||
|
documentControls.navigationControlView.forwardButton.isEnabled = webView.canGoForward
|
||||||
|
documentControls.navigationControlView.forwardButton.addAction(UIAction() { [unowned self] _ in
|
||||||
|
webView.goForward()
|
||||||
|
}, for: .touchUpInside)
|
||||||
|
|
||||||
|
documentControls.observations.append(webView.observe(\.canGoForward, changeHandler: { (_, _) in
|
||||||
|
documentControls.navigationControlView.forwardButton.isEnabled = webView.canGoForward
|
||||||
|
}))
|
||||||
|
|
||||||
present(documentControls, animated: true, completion: nil)
|
present(documentControls, animated: true, completion: nil)
|
||||||
}), for: .touchUpInside)
|
}), for: .touchUpInside)
|
||||||
|
|
||||||
|
|||||||
@@ -7,26 +7,33 @@
|
|||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
class StackView: UIView
|
class StackView<T: UIView>: UIView
|
||||||
{
|
{
|
||||||
var arrangedSubviews: [UIView] = []
|
public enum LayoutType {
|
||||||
|
case intrinsicSize
|
||||||
|
case equalSize
|
||||||
|
}
|
||||||
|
|
||||||
|
var arrangedSubviews: [T] = []
|
||||||
{ didSet { setNeedsLayout() } }
|
{ didSet { setNeedsLayout() } }
|
||||||
|
|
||||||
var layoutDimension: UIAxis = .vertical
|
var layoutDimension: UIAxis = .vertical
|
||||||
|
var layoutType: LayoutType = .intrinsicSize
|
||||||
|
|
||||||
convenience init(dimension: UIAxis) {
|
convenience init(dimension: UIAxis = .vertical, layoutType: LayoutType = .intrinsicSize) {
|
||||||
self.init(frame: .zero)
|
self.init(frame: .zero)
|
||||||
self.layoutDimension = dimension
|
self.layoutDimension = dimension
|
||||||
|
self.layoutType = layoutType
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convenience
|
// Convenience
|
||||||
public func addArrangedSubview(_ view: UIView) {
|
public func addArrangedSubview(_ view: T) {
|
||||||
addSubview(view)
|
addSubview(view)
|
||||||
arrangedSubviews.append(view)
|
arrangedSubviews.append(view)
|
||||||
setNeedsLayout()
|
setNeedsLayout()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func removeArrangedSubview(_ view: UIView) {
|
public func removeArrangedSubview(_ view: T) {
|
||||||
if view.superview == self {
|
if view.superview == self {
|
||||||
view.removeFromSuperview()
|
view.removeFromSuperview()
|
||||||
}
|
}
|
||||||
@@ -68,6 +75,16 @@ class StackView: UIView
|
|||||||
override func layoutSubviews() {
|
override func layoutSubviews() {
|
||||||
super.layoutSubviews()
|
super.layoutSubviews()
|
||||||
|
|
||||||
|
if layoutType == .intrinsicSize {
|
||||||
|
layoutWithIntrinsicSize()
|
||||||
|
} else if layoutType == .equalSize {
|
||||||
|
layoutWithEqualSize()
|
||||||
|
} else {
|
||||||
|
fatalError("StackView: I don't know how to lay out this type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func layoutWithIntrinsicSize() {
|
||||||
var origin: CGPoint = CGPoint(x: safeAreaInsets.left, y: safeAreaInsets.top)
|
var origin: CGPoint = CGPoint(x: safeAreaInsets.left, y: safeAreaInsets.top)
|
||||||
var spaceRemaining = bounds.size
|
var spaceRemaining = bounds.size
|
||||||
for view in arrangedSubviews {
|
for view in arrangedSubviews {
|
||||||
@@ -88,5 +105,35 @@ class StackView: UIView
|
|||||||
origin.x += offset.x
|
origin.x += offset.x
|
||||||
origin.y += offset.y
|
origin.y += offset.y
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func layoutWithEqualSize() {
|
||||||
|
let numberOfItems = arrangedSubviews.count
|
||||||
|
|
||||||
|
let structureDimension: CGFloat = (
|
||||||
|
(layoutDimension == .horizontal) ? bounds.height : bounds.width
|
||||||
|
)
|
||||||
|
|
||||||
|
let itemDimension: CGFloat = (
|
||||||
|
(layoutDimension == .horizontal) ? (bounds.width / CGFloat(numberOfItems)) : (bounds.height / CGFloat(numberOfItems))
|
||||||
|
)
|
||||||
|
|
||||||
|
var origin: CGPoint = CGPoint(x: safeAreaInsets.left, y: safeAreaInsets.top)
|
||||||
|
for view in arrangedSubviews {
|
||||||
|
let size: CGSize = (
|
||||||
|
(layoutDimension == .horizontal)
|
||||||
|
? CGSize(width: itemDimension, height: structureDimension)
|
||||||
|
: CGSize(width: structureDimension, height: itemDimension)
|
||||||
|
)
|
||||||
|
|
||||||
|
view.frame = CGRect(origin: origin, size: size)
|
||||||
|
|
||||||
|
origin = (
|
||||||
|
(layoutDimension == .horizontal)
|
||||||
|
? CGPoint(x: origin.x + size.width, y: origin.y)
|
||||||
|
: CGPoint(x: origin.x, y: origin.y + size.height)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,8 +31,8 @@ class DocumentControlView: UIControl
|
|||||||
|
|
||||||
tintColor = .label
|
tintColor = .label
|
||||||
|
|
||||||
label.font = UIFont.preferredFont(forTextStyle: .subheadline)
|
label.font = UIFont.preferredFont(forTextStyle: .body)
|
||||||
label.textAlignment = .center
|
label.textAlignment = .left
|
||||||
|
|
||||||
imageView.contentMode = .center
|
imageView.contentMode = .center
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,12 @@ import UIKit
|
|||||||
|
|
||||||
class DocumentControlViewController: UIViewController
|
class DocumentControlViewController: UIViewController
|
||||||
{
|
{
|
||||||
let documentControlView = StackView(dimension: .vertical)
|
let documentControlView = StackView<DocumentControlView>(dimension: .vertical)
|
||||||
let fontSizeAdjustView = FontSizeAdjustView()
|
let fontSizeAdjustView = FontSizeAdjustView()
|
||||||
let findOnPageControlView = DocumentControlView()
|
let findOnPageControlView = DocumentControlView()
|
||||||
|
let navigationControlView = NavigationControlsView()
|
||||||
|
|
||||||
|
var observations: [NSKeyValueObservation] = []
|
||||||
|
|
||||||
static public let preferredWidth = CGFloat(200.0)
|
static public let preferredWidth = CGFloat(200.0)
|
||||||
|
|
||||||
@@ -21,10 +24,13 @@ class DocumentControlViewController: UIViewController
|
|||||||
findOnPageControlView.label.text = "Find On Page"
|
findOnPageControlView.label.text = "Find On Page"
|
||||||
findOnPageControlView.imageView.image = UIImage(systemName: "magnifyingglass")
|
findOnPageControlView.imageView.image = UIImage(systemName: "magnifyingglass")
|
||||||
|
|
||||||
fontSizeAdjustView.drawsBottomSeparator = true
|
documentControlView.addArrangedSubview(navigationControlView)
|
||||||
|
|
||||||
documentControlView.addArrangedSubview(fontSizeAdjustView)
|
documentControlView.addArrangedSubview(fontSizeAdjustView)
|
||||||
documentControlView.addArrangedSubview(findOnPageControlView)
|
documentControlView.addArrangedSubview(findOnPageControlView)
|
||||||
|
|
||||||
|
for (i, view) in documentControlView.arrangedSubviews.enumerated() {
|
||||||
|
view.drawsBottomSeparator = (i < documentControlView.arrangedSubviews.count - 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func loadView() {
|
override func loadView() {
|
||||||
|
|||||||
37
App/Document Controls UI/NavigationControlsView.swift
Normal file
37
App/Document Controls UI/NavigationControlsView.swift
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
//
|
||||||
|
// NavigationControlsView.swift
|
||||||
|
// App
|
||||||
|
//
|
||||||
|
// Created by James Magahern on 2/11/21.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class NavigationControlsView: DocumentControlView
|
||||||
|
{
|
||||||
|
let backButton = UIButton(frame: .zero)
|
||||||
|
let forwardButton = UIButton(frame: .zero)
|
||||||
|
|
||||||
|
let stack = StackView(dimension: .horizontal, layoutType: .equalSize)
|
||||||
|
|
||||||
|
override init() {
|
||||||
|
super.init()
|
||||||
|
|
||||||
|
backButton.setImage(UIImage(systemName: "chevron.left"), for: .normal)
|
||||||
|
stack.addArrangedSubview(backButton)
|
||||||
|
|
||||||
|
forwardButton.setImage(UIImage(systemName: "chevron.right"), for: .normal)
|
||||||
|
stack.addArrangedSubview(forwardButton)
|
||||||
|
|
||||||
|
addSubview(stack)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override func layoutSubviews() {
|
||||||
|
super.layoutSubviews()
|
||||||
|
stack.frame = bounds
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -29,7 +29,7 @@ class URLBar: ReliefButton
|
|||||||
private let progressIndicatorView = ProgressIndicatorView()
|
private let progressIndicatorView = ProgressIndicatorView()
|
||||||
private var progressIndicatorAnimating = false
|
private var progressIndicatorAnimating = false
|
||||||
|
|
||||||
private let documentImage = UIImage(systemName: "doc.plaintext")
|
private let documentImage = UIImage(systemName: "filemenu.and.selection")
|
||||||
private let refreshImage = UIImage(systemName: "arrow.clockwise")
|
private let refreshImage = UIImage(systemName: "arrow.clockwise")
|
||||||
private let stopImage = UIImage(systemName: "xmark")
|
private let stopImage = UIImage(systemName: "xmark")
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
CD853BCE24E7763900D2BDCC /* BrowserHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD853BCD24E7763900D2BDCC /* BrowserHistory.swift */; };
|
CD853BCE24E7763900D2BDCC /* BrowserHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD853BCD24E7763900D2BDCC /* BrowserHistory.swift */; };
|
||||||
CD853BD124E778B800D2BDCC /* History.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = CD853BCF24E778B800D2BDCC /* History.xcdatamodeld */; };
|
CD853BD124E778B800D2BDCC /* History.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = CD853BCF24E778B800D2BDCC /* History.xcdatamodeld */; };
|
||||||
CD853BD424E77BF900D2BDCC /* HistoryItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD853BD324E77BF900D2BDCC /* HistoryItem.swift */; };
|
CD853BD424E77BF900D2BDCC /* HistoryItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD853BD324E77BF900D2BDCC /* HistoryItem.swift */; };
|
||||||
|
CD97CF9225D5BE6F00288FEE /* NavigationControlsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD97CF9125D5BE6F00288FEE /* NavigationControlsView.swift */; };
|
||||||
CDCE2664251AA80F007FE92A /* DocumentControlViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDCE2663251AA80F007FE92A /* DocumentControlViewController.swift */; };
|
CDCE2664251AA80F007FE92A /* DocumentControlViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDCE2663251AA80F007FE92A /* DocumentControlViewController.swift */; };
|
||||||
CDCE2666251AA840007FE92A /* StackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDCE2665251AA840007FE92A /* StackView.swift */; };
|
CDCE2666251AA840007FE92A /* StackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDCE2665251AA840007FE92A /* StackView.swift */; };
|
||||||
CDCE2668251AAA9A007FE92A /* FontSizeAdjustView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDCE2667251AAA9A007FE92A /* FontSizeAdjustView.swift */; };
|
CDCE2668251AAA9A007FE92A /* FontSizeAdjustView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDCE2667251AAA9A007FE92A /* FontSizeAdjustView.swift */; };
|
||||||
@@ -128,6 +129,7 @@
|
|||||||
CD853BCD24E7763900D2BDCC /* BrowserHistory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserHistory.swift; sourceTree = "<group>"; };
|
CD853BCD24E7763900D2BDCC /* BrowserHistory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserHistory.swift; sourceTree = "<group>"; };
|
||||||
CD853BD024E778B800D2BDCC /* History.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = History.xcdatamodel; sourceTree = "<group>"; };
|
CD853BD024E778B800D2BDCC /* History.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = History.xcdatamodel; sourceTree = "<group>"; };
|
||||||
CD853BD324E77BF900D2BDCC /* HistoryItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryItem.swift; sourceTree = "<group>"; };
|
CD853BD324E77BF900D2BDCC /* HistoryItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryItem.swift; sourceTree = "<group>"; };
|
||||||
|
CD97CF9125D5BE6F00288FEE /* NavigationControlsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationControlsView.swift; sourceTree = "<group>"; };
|
||||||
CDCE2663251AA80F007FE92A /* DocumentControlViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentControlViewController.swift; sourceTree = "<group>"; };
|
CDCE2663251AA80F007FE92A /* DocumentControlViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentControlViewController.swift; sourceTree = "<group>"; };
|
||||||
CDCE2665251AA840007FE92A /* StackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackView.swift; sourceTree = "<group>"; };
|
CDCE2665251AA840007FE92A /* StackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackView.swift; sourceTree = "<group>"; };
|
||||||
CDCE2667251AAA9A007FE92A /* FontSizeAdjustView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontSizeAdjustView.swift; sourceTree = "<group>"; };
|
CDCE2667251AAA9A007FE92A /* FontSizeAdjustView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontSizeAdjustView.swift; sourceTree = "<group>"; };
|
||||||
@@ -158,6 +160,7 @@
|
|||||||
1A03811124E71EAA00826501 /* GradientView.swift */,
|
1A03811124E71EAA00826501 /* GradientView.swift */,
|
||||||
1A03810F24E71CF000826501 /* ReliefButton.swift */,
|
1A03810F24E71CF000826501 /* ReliefButton.swift */,
|
||||||
1A03811324E73EB300826501 /* SegmentedReliefButton.swift */,
|
1A03811324E73EB300826501 /* SegmentedReliefButton.swift */,
|
||||||
|
CDCE2665251AA840007FE92A /* StackView.swift */,
|
||||||
);
|
);
|
||||||
path = "Common UI";
|
path = "Common UI";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -309,7 +312,6 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
1ADFF4C224CA6AF6006DC7AE /* Geometry.swift */,
|
1ADFF4C224CA6AF6006DC7AE /* Geometry.swift */,
|
||||||
CDCE2665251AA840007FE92A /* StackView.swift */,
|
|
||||||
CD7A8918251989C90075991E /* UIKeyCommand+ConvInit.swift */,
|
CD7A8918251989C90075991E /* UIKeyCommand+ConvInit.swift */,
|
||||||
1ADFF4C624CA6DEB006DC7AE /* UIEdgeInsets+Layout.swift */,
|
1ADFF4C624CA6DEB006DC7AE /* UIEdgeInsets+Layout.swift */,
|
||||||
1AB88F0524D4D3A90006F850 /* UIGestureRecognizer+Actions.swift */,
|
1AB88F0524D4D3A90006F850 /* UIGestureRecognizer+Actions.swift */,
|
||||||
@@ -351,6 +353,7 @@
|
|||||||
CDCE2663251AA80F007FE92A /* DocumentControlViewController.swift */,
|
CDCE2663251AA80F007FE92A /* DocumentControlViewController.swift */,
|
||||||
1AD310442525586B00A4A952 /* DocumentControlView.swift */,
|
1AD310442525586B00A4A952 /* DocumentControlView.swift */,
|
||||||
CDCE2667251AAA9A007FE92A /* FontSizeAdjustView.swift */,
|
CDCE2667251AAA9A007FE92A /* FontSizeAdjustView.swift */,
|
||||||
|
CD97CF9125D5BE6F00288FEE /* NavigationControlsView.swift */,
|
||||||
);
|
);
|
||||||
path = "Document Controls UI";
|
path = "Document Controls UI";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -494,6 +497,7 @@
|
|||||||
1AB88EFF24D3BBA50006F850 /* TabPickerViewController.swift in Sources */,
|
1AB88EFF24D3BBA50006F850 /* TabPickerViewController.swift in Sources */,
|
||||||
1A14FC2324D203D9009B3F83 /* TitlebarView.swift in Sources */,
|
1A14FC2324D203D9009B3F83 /* TitlebarView.swift in Sources */,
|
||||||
1AD310452525586B00A4A952 /* DocumentControlView.swift in Sources */,
|
1AD310452525586B00A4A952 /* DocumentControlView.swift in Sources */,
|
||||||
|
CD97CF9225D5BE6F00288FEE /* NavigationControlsView.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user