From 399e77937144c4c7131f7c2bde9ffa1db9cdca37 Mon Sep 17 00:00:00 2001 From: James Magahern Date: Tue, 22 Sep 2020 15:37:13 -0700 Subject: [PATCH] Font size adjustment --- App/Browser View/BrowserViewController.swift | 27 ++++++ .../DocumentControlViewController.swift | 32 +++++++ .../FontSizeAdjustView.swift | 58 ++++++++++++ .../SBrowser-Bridging-Header.h | 1 + App/Titlebar and URL Bar/URLBar.swift | 33 ++++++- App/Utilities/StackView.swift | 92 +++++++++++++++++++ SBrowser.xcodeproj/project.pbxproj | 20 ++++ 7 files changed, 262 insertions(+), 1 deletion(-) create mode 100644 App/Document Controls UI/DocumentControlViewController.swift create mode 100644 App/Document Controls UI/FontSizeAdjustView.swift create mode 100644 App/Utilities/StackView.swift diff --git a/App/Browser View/BrowserViewController.swift b/App/Browser View/BrowserViewController.swift index 5f937f1..ce2031e 100644 --- a/App/Browser View/BrowserViewController.swift +++ b/App/Browser View/BrowserViewController.swift @@ -173,6 +173,33 @@ class BrowserViewController: UIViewController, WKNavigationDelegate, WKUIDelegat autocompleteViewController.delegate = self autocompleteViewController.view.isHidden = true + // Font size adjust + toolbarController.urlBar.documentButton.addAction(UIAction(handler: { [unowned self] _ in + let documentControls = DocumentControlViewController() + documentControls.modalPresentationStyle = .popover + documentControls.popoverPresentationController?.permittedArrowDirections = [ .down, .up ] + documentControls.popoverPresentationController?.sourceView = toolbarController.urlBar.documentButton + documentControls.popoverPresentationController?.delegate = self + + let numberFormatter = NumberFormatter() + numberFormatter.numberStyle = .percent + + let label = documentControls.fontSizeAdjustView.labelView + label.text = numberFormatter.string(for: tab.webView._viewScale) + + documentControls.fontSizeAdjustView.decreaseSizeButton.addAction(UIAction(handler: { [unowned self] _ in + tab.webView._viewScale -= 0.10 + label.text = numberFormatter.string(for: tab.webView._viewScale) + }), for: .touchUpInside) + + documentControls.fontSizeAdjustView.increaseSizeButton.addAction(UIAction(handler: { [unowned self] _ in + tab.webView._viewScale += 0.10 + label.text = numberFormatter.string(for: tab.webView._viewScale) + }), for: .touchUpInside) + + present(documentControls, animated: true, completion: nil) + }), for: .touchUpInside) + self.view = browserView } diff --git a/App/Document Controls UI/DocumentControlViewController.swift b/App/Document Controls UI/DocumentControlViewController.swift new file mode 100644 index 0000000..dcc1621 --- /dev/null +++ b/App/Document Controls UI/DocumentControlViewController.swift @@ -0,0 +1,32 @@ +// +// DocumentControlViewController.swift +// App +// +// Created by James Magahern on 9/22/20. +// + +import UIKit + +class DocumentControlViewController: UIViewController +{ + let documentControlView = StackView(dimension: .vertical) + let fontSizeAdjustView = FontSizeAdjustView() + + static public let preferredWidth = CGFloat(200.0) + static public let controlHeight = CGFloat(48.0) + + convenience init() { + self.init(nibName: nil, bundle: nil) + + documentControlView.addArrangedSubview(fontSizeAdjustView) + } + + override func loadView() { + self.view = documentControlView + } + + override var preferredContentSize: CGSize { + get { documentControlView.sizeThatFits(CGSize(width: Self.preferredWidth, height: -1)) } + set {} + } +} diff --git a/App/Document Controls UI/FontSizeAdjustView.swift b/App/Document Controls UI/FontSizeAdjustView.swift new file mode 100644 index 0000000..641673b --- /dev/null +++ b/App/Document Controls UI/FontSizeAdjustView.swift @@ -0,0 +1,58 @@ +// +// FontSizeAdjustView.swift +// App +// +// Created by James Magahern on 9/22/20. +// + +import UIKit + +class FontSizeAdjustView: UIView +{ + let decreaseSizeButton = UIButton(frame: .zero) + let increaseSizeButton = UIButton(frame: .zero) + let labelView = UILabel(frame: .zero) + + convenience init() { + self.init(frame: .zero) + + labelView.textColor = .secondaryLabel + labelView.textAlignment = .center + labelView.text = "100%" + + tintColor = .black + + decreaseSizeButton.setImage(UIImage(systemName: "minus"), for: .normal) + increaseSizeButton.setImage(UIImage(systemName: "plus"), for: .normal) + + addSubview(increaseSizeButton) + addSubview(decreaseSizeButton) + addSubview(labelView) + } + + override func sizeThatFits(_ size: CGSize) -> CGSize { + CGSize(width: size.width, height: DocumentControlViewController.controlHeight) + } + + override func layoutSubviews() { + super.layoutSubviews() + + decreaseSizeButton.frame = CGRect( + x: 0.0, y: 0.0, + width: bounds.height, + height: bounds.height + ) + + increaseSizeButton.frame = CGRect( + x: bounds.width - bounds.height, y: 0.0, + width: bounds.height, + height: bounds.height + ) + + labelView.frame = CGRect( + x: decreaseSizeButton.frame.maxX, y: 0.0, + width: bounds.width - decreaseSizeButton.frame.width - increaseSizeButton.frame.width, + height: bounds.height + ) + } +} diff --git a/App/Supporting Files/SBrowser-Bridging-Header.h b/App/Supporting Files/SBrowser-Bridging-Header.h index 8b4d486..a9ad118 100644 --- a/App/Supporting Files/SBrowser-Bridging-Header.h +++ b/App/Supporting Files/SBrowser-Bridging-Header.h @@ -6,3 +6,4 @@ // SPI #import +#import diff --git a/App/Titlebar and URL Bar/URLBar.swift b/App/Titlebar and URL Bar/URLBar.swift index ebc6b28..8146dd8 100644 --- a/App/Titlebar and URL Bar/URLBar.swift +++ b/App/Titlebar and URL Bar/URLBar.swift @@ -12,6 +12,7 @@ class URLBar: ReliefButton let textField = UITextField(frame: .zero) let refreshButton = UIButton(frame: .zero) let errorButton = UIButton(frame: .zero) + let documentButton = UIButton(frame: .zero) public enum LoadProgress { case complete @@ -28,11 +29,14 @@ class URLBar: ReliefButton private let progressIndicatorView = ProgressIndicatorView() private var progressIndicatorAnimating = false + private let documentImage = UIImage(systemName: "doc.plaintext") private let refreshImage = UIImage(systemName: "arrow.clockwise") private let stopImage = UIImage(systemName: "xmark") private let backgroundCornerRadius: CGFloat = 0 + private let documentSeparatorView = UIView(frame: .zero) + override init() { super.init() @@ -70,6 +74,13 @@ class URLBar: ReliefButton errorButton.setTitle("ERR", for: .normal) addSubview(errorButton) + documentButton.tintColor = .secondaryLabel + documentButton.setImage(documentImage, for: .normal) + addSubview(documentButton) + + documentSeparatorView.backgroundColor = .secondarySystemFill + addSubview(documentSeparatorView) + setErrorButtonAnimating(false) } @@ -172,7 +183,27 @@ class URLBar: ReliefButton backgroundView.frame = bounds shadowView.frame = bounds progressIndicatorView.frame = backgroundView.bounds - textField.frame = bounds.insetBy(dx: 6.0, dy: 0) + + // Document button + documentButton.frame = CGRect(x: 0.0, y: 0.0, width: bounds.height, height: bounds.height) + + // Document separator + documentSeparatorView.frame = CGRect( + x: documentButton.frame.maxX, y: 0.0, + width: 1.0, height: bounds.height + ) + documentSeparatorView.frame = documentSeparatorView.frame.insetBy(dx: 0.0, dy: 3.0) + + // Text field + let textFieldPadding: CGFloat = 5.0 + let textFieldOrigin = CGPoint(x: documentButton.frame.maxX + textFieldPadding, y: 0.0) + textField.frame = CGRect( + origin: textFieldOrigin, + size: CGSize( + width: bounds.width - textFieldOrigin.x - textFieldPadding, + height: bounds.height + ) + ) var fadeCutoffLocation: CGFloat = 0.8 diff --git a/App/Utilities/StackView.swift b/App/Utilities/StackView.swift new file mode 100644 index 0000000..21a41e5 --- /dev/null +++ b/App/Utilities/StackView.swift @@ -0,0 +1,92 @@ +// +// StackView.swift +// App +// +// Created by James Magahern on 9/22/20. +// + +import UIKit + +class StackView: UIView +{ + var arrangedSubviews: [UIView] = [] + { didSet { setNeedsLayout() } } + + var layoutDimension: UIAxis = .vertical + + convenience init(dimension: UIAxis) { + self.init(frame: .zero) + self.layoutDimension = dimension + } + + // Convenience + public func addArrangedSubview(_ view: UIView) { + addSubview(view) + arrangedSubviews.append(view) + setNeedsLayout() + } + + public func removeArrangedSubview(_ view: UIView) { + if view.superview == self { + view.removeFromSuperview() + } + + arrangedSubviews.removeAll { $0 == view } + setNeedsLayout() + } + + public func removeAllArrangedSubviews() { + arrangedSubviews.forEach { $0.removeFromSuperview() } + arrangedSubviews.removeAll() + setNeedsLayout() + } + + override func sizeThatFits(_ containerSize: CGSize) -> CGSize { + var size: CGSize = .zero + + if layoutDimension == .horizontal { + size.height = containerSize.height + } else { + size.width = containerSize.width + } + + var spaceRemaining = containerSize + for view in arrangedSubviews { + let viewSize = view.sizeThatFits(spaceRemaining) + if layoutDimension == .horizontal { + size.width += viewSize.width + spaceRemaining.width -= viewSize.width + } else { + size.height += viewSize.height + spaceRemaining.height -= viewSize.height + } + } + + return size + } + + override func layoutSubviews() { + super.layoutSubviews() + + var origin: CGPoint = CGPoint(x: safeAreaInsets.left, y: safeAreaInsets.top) + var spaceRemaining = bounds.size + for view in arrangedSubviews { + var viewSize = view.sizeThatFits(spaceRemaining) + + var offset: CGPoint = .zero + if layoutDimension == .horizontal { + offset.x = viewSize.width + viewSize.height = bounds.height + spaceRemaining.width -= viewSize.width + } else { + offset.y = viewSize.height + viewSize.width = bounds.width + spaceRemaining.height -= viewSize.height + } + + view.frame = CGRect(origin: origin, size: viewSize) + origin.x += offset.x + origin.y += offset.y + } + } +} diff --git a/SBrowser.xcodeproj/project.pbxproj b/SBrowser.xcodeproj/project.pbxproj index ee6d955..d36a009 100644 --- a/SBrowser.xcodeproj/project.pbxproj +++ b/SBrowser.xcodeproj/project.pbxproj @@ -42,6 +42,9 @@ 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 */; }; + 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 */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -113,6 +116,9 @@ 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 = ""; }; + 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 = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -203,6 +209,7 @@ 1ADFF47A24C7E176006DC7AE /* Backend */, 1ADFF47724C7DFE8006DC7AE /* Browser View */, 1A03810E24E71CCA00826501 /* Common UI */, + CDCE2662251AA7FC007FE92A /* Document Controls UI */, 1ADFF4CE24CBBCBD006DC7AE /* Script Policy UI */, 1AB88F0324D3E1EC0006F850 /* Tabs */, 1AB88F0424D3E1F90006F850 /* Titlebar and URL Bar */, @@ -277,6 +284,7 @@ isa = PBXGroup; children = ( 1ADFF4C224CA6AF6006DC7AE /* Geometry.swift */, + CDCE2665251AA840007FE92A /* StackView.swift */, CD7A8918251989C90075991E /* UIKeyCommand+ConvInit.swift */, 1ADFF4C624CA6DEB006DC7AE /* UIEdgeInsets+Layout.swift */, 1AB88F0524D4D3A90006F850 /* UIGestureRecognizer+Actions.swift */, @@ -312,6 +320,15 @@ path = History; sourceTree = ""; }; + CDCE2662251AA7FC007FE92A /* Document Controls UI */ = { + isa = PBXGroup; + children = ( + CDCE2663251AA80F007FE92A /* DocumentControlViewController.swift */, + CDCE2667251AAA9A007FE92A /* FontSizeAdjustView.swift */, + ); + path = "Document Controls UI"; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -418,11 +435,13 @@ 1A03811024E71CF000826501 /* ReliefButton.swift in Sources */, 1A03811224E71EAA00826501 /* GradientView.swift in Sources */, 1ADFF4C024CA6964006DC7AE /* URLBar.swift in Sources */, + CDCE2666251AA840007FE92A /* StackView.swift in Sources */, CD853BD124E778B800D2BDCC /* History.xcdatamodeld in Sources */, CD7A8919251989C90075991E /* UIKeyCommand+ConvInit.swift in Sources */, 1ADFF4C724CA6DEB006DC7AE /* UIEdgeInsets+Layout.swift in Sources */, 1ADFF4AE24C8ED32006DC7AE /* ResourcePolicyManager.swift in Sources */, 1ADFF47424C7DE9C006DC7AE /* BrowserViewController.swift in Sources */, + CDCE2668251AAA9A007FE92A /* FontSizeAdjustView.swift in Sources */, 1ADFF4D024CBBCD1006DC7AE /* ScriptPolicyControl.swift in Sources */, 1A03810D24E71CA700826501 /* ToolbarView.swift in Sources */, CD853BD424E77BF900D2BDCC /* HistoryItem.swift in Sources */, @@ -440,6 +459,7 @@ 1ADFF4CD24CBB0C8006DC7AE /* ScriptPolicyViewController.swift in Sources */, 1A14FC2824D26749009B3F83 /* Tab.swift in Sources */, 1ADFF47924C7DFF8006DC7AE /* BrowserView.swift in Sources */, + CDCE2664251AA80F007FE92A /* DocumentControlViewController.swift in Sources */, 1AB88EFF24D3BBA50006F850 /* TabPickerViewController.swift in Sources */, 1A14FC2324D203D9009B3F83 /* TitlebarView.swift in Sources */, );