From f32c90f2e313c56bf21de423f50e29922d2463de Mon Sep 17 00:00:00 2001 From: James Magahern Date: Thu, 11 Feb 2021 12:26:13 -0800 Subject: [PATCH] Adds back/forward buttons to page menu --- App/Browser View/BrowserViewController.swift | 21 +++++++ App/{Utilities => Common UI}/StackView.swift | 57 +++++++++++++++++-- .../DocumentControlView.swift | 4 +- .../DocumentControlViewController.swift | 12 +++- .../NavigationControlsView.swift | 37 ++++++++++++ App/Titlebar and URL Bar/URLBar.swift | 2 +- SBrowser.xcodeproj/project.pbxproj | 6 +- 7 files changed, 127 insertions(+), 12 deletions(-) rename App/{Utilities => Common UI}/StackView.swift (55%) create mode 100644 App/Document Controls UI/NavigationControlsView.swift diff --git a/App/Browser View/BrowserViewController.swift b/App/Browser View/BrowserViewController.swift index 0d5d87d..06af7bd 100644 --- a/App/Browser View/BrowserViewController.swift +++ b/App/Browser View/BrowserViewController.swift @@ -203,6 +203,7 @@ class BrowserViewController: UIViewController, WKNavigationDelegate, WKUIDelegat let label = documentControls.fontSizeAdjustView.labelView label.text = numberFormatter.string(for: tab.webView._viewScale) + // Font size adjust documentControls.fontSizeAdjustView.decreaseSizeButton.addAction(UIAction(handler: { [unowned self] sender in self.decreaseSize(sender) 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) }), for: .touchUpInside) + // Find on page documentControls.findOnPageControlView.addAction(UIAction(handler: { [unowned self] _ in documentControls.dismiss(animated: true, completion: nil) browserView.setFindOnPageVisible(true, animated: true) }), 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) }), for: .touchUpInside) diff --git a/App/Utilities/StackView.swift b/App/Common UI/StackView.swift similarity index 55% rename from App/Utilities/StackView.swift rename to App/Common UI/StackView.swift index 21a41e5..33533bc 100644 --- a/App/Utilities/StackView.swift +++ b/App/Common UI/StackView.swift @@ -7,26 +7,33 @@ import UIKit -class StackView: UIView +class StackView: UIView { - var arrangedSubviews: [UIView] = [] + public enum LayoutType { + case intrinsicSize + case equalSize + } + + var arrangedSubviews: [T] = [] { didSet { setNeedsLayout() } } 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.layoutDimension = dimension + self.layoutType = layoutType } // Convenience - public func addArrangedSubview(_ view: UIView) { + public func addArrangedSubview(_ view: T) { addSubview(view) arrangedSubviews.append(view) setNeedsLayout() } - public func removeArrangedSubview(_ view: UIView) { + public func removeArrangedSubview(_ view: T) { if view.superview == self { view.removeFromSuperview() } @@ -68,6 +75,16 @@ class StackView: UIView override func 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 spaceRemaining = bounds.size for view in arrangedSubviews { @@ -88,5 +105,35 @@ class StackView: UIView origin.x += offset.x 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) + ) + } } } diff --git a/App/Document Controls UI/DocumentControlView.swift b/App/Document Controls UI/DocumentControlView.swift index dca54a0..0fb8a96 100644 --- a/App/Document Controls UI/DocumentControlView.swift +++ b/App/Document Controls UI/DocumentControlView.swift @@ -31,8 +31,8 @@ class DocumentControlView: UIControl tintColor = .label - label.font = UIFont.preferredFont(forTextStyle: .subheadline) - label.textAlignment = .center + label.font = UIFont.preferredFont(forTextStyle: .body) + label.textAlignment = .left imageView.contentMode = .center diff --git a/App/Document Controls UI/DocumentControlViewController.swift b/App/Document Controls UI/DocumentControlViewController.swift index ae17c6b..01963dc 100644 --- a/App/Document Controls UI/DocumentControlViewController.swift +++ b/App/Document Controls UI/DocumentControlViewController.swift @@ -9,9 +9,12 @@ import UIKit class DocumentControlViewController: UIViewController { - let documentControlView = StackView(dimension: .vertical) + let documentControlView = StackView(dimension: .vertical) let fontSizeAdjustView = FontSizeAdjustView() let findOnPageControlView = DocumentControlView() + let navigationControlView = NavigationControlsView() + + var observations: [NSKeyValueObservation] = [] static public let preferredWidth = CGFloat(200.0) @@ -21,10 +24,13 @@ class DocumentControlViewController: UIViewController findOnPageControlView.label.text = "Find On Page" findOnPageControlView.imageView.image = UIImage(systemName: "magnifyingglass") - fontSizeAdjustView.drawsBottomSeparator = true - + documentControlView.addArrangedSubview(navigationControlView) documentControlView.addArrangedSubview(fontSizeAdjustView) documentControlView.addArrangedSubview(findOnPageControlView) + + for (i, view) in documentControlView.arrangedSubviews.enumerated() { + view.drawsBottomSeparator = (i < documentControlView.arrangedSubviews.count - 1) + } } override func loadView() { diff --git a/App/Document Controls UI/NavigationControlsView.swift b/App/Document Controls UI/NavigationControlsView.swift new file mode 100644 index 0000000..45fbae6 --- /dev/null +++ b/App/Document Controls UI/NavigationControlsView.swift @@ -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 + } +} diff --git a/App/Titlebar and URL Bar/URLBar.swift b/App/Titlebar and URL Bar/URLBar.swift index f6d06a6..ecdbb40 100644 --- a/App/Titlebar and URL Bar/URLBar.swift +++ b/App/Titlebar and URL Bar/URLBar.swift @@ -29,7 +29,7 @@ class URLBar: ReliefButton private let progressIndicatorView = ProgressIndicatorView() 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 stopImage = UIImage(systemName: "xmark") diff --git a/SBrowser.xcodeproj/project.pbxproj b/SBrowser.xcodeproj/project.pbxproj index 6453ca6..f7be5c6 100644 --- a/SBrowser.xcodeproj/project.pbxproj +++ b/SBrowser.xcodeproj/project.pbxproj @@ -48,6 +48,7 @@ CD853BCE24E7763900D2BDCC /* BrowserHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD853BCD24E7763900D2BDCC /* BrowserHistory.swift */; }; CD853BD124E778B800D2BDCC /* History.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = CD853BCF24E778B800D2BDCC /* History.xcdatamodeld */; }; 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 */; }; CDCE2666251AA840007FE92A /* StackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDCE2665251AA840007FE92A /* StackView.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 = ""; }; CD853BD024E778B800D2BDCC /* History.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = History.xcdatamodel; sourceTree = ""; }; CD853BD324E77BF900D2BDCC /* HistoryItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryItem.swift; sourceTree = ""; }; + CD97CF9125D5BE6F00288FEE /* NavigationControlsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationControlsView.swift; sourceTree = ""; }; CDCE2663251AA80F007FE92A /* DocumentControlViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentControlViewController.swift; sourceTree = ""; }; CDCE2665251AA840007FE92A /* StackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackView.swift; sourceTree = ""; }; CDCE2667251AAA9A007FE92A /* FontSizeAdjustView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontSizeAdjustView.swift; sourceTree = ""; }; @@ -158,6 +160,7 @@ 1A03811124E71EAA00826501 /* GradientView.swift */, 1A03810F24E71CF000826501 /* ReliefButton.swift */, 1A03811324E73EB300826501 /* SegmentedReliefButton.swift */, + CDCE2665251AA840007FE92A /* StackView.swift */, ); path = "Common UI"; sourceTree = ""; @@ -309,7 +312,6 @@ isa = PBXGroup; children = ( 1ADFF4C224CA6AF6006DC7AE /* Geometry.swift */, - CDCE2665251AA840007FE92A /* StackView.swift */, CD7A8918251989C90075991E /* UIKeyCommand+ConvInit.swift */, 1ADFF4C624CA6DEB006DC7AE /* UIEdgeInsets+Layout.swift */, 1AB88F0524D4D3A90006F850 /* UIGestureRecognizer+Actions.swift */, @@ -351,6 +353,7 @@ CDCE2663251AA80F007FE92A /* DocumentControlViewController.swift */, 1AD310442525586B00A4A952 /* DocumentControlView.swift */, CDCE2667251AAA9A007FE92A /* FontSizeAdjustView.swift */, + CD97CF9125D5BE6F00288FEE /* NavigationControlsView.swift */, ); path = "Document Controls UI"; sourceTree = ""; @@ -494,6 +497,7 @@ 1AB88EFF24D3BBA50006F850 /* TabPickerViewController.swift in Sources */, 1A14FC2324D203D9009B3F83 /* TitlebarView.swift in Sources */, 1AD310452525586B00A4A952 /* DocumentControlView.swift in Sources */, + CD97CF9225D5BE6F00288FEE /* NavigationControlsView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };