Adds back/forward buttons to page menu

This commit is contained in:
James Magahern
2021-02-11 12:26:13 -08:00
parent bd400a006d
commit f32c90f2e3
7 changed files with 127 additions and 12 deletions

View File

@@ -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)

View File

@@ -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)
)
}
} }
} }

View File

@@ -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

View File

@@ -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() {

View 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
}
}

View File

@@ -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")

View File

@@ -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;
}; };