mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-02 17:40:23 +08:00
* Using shadows on all texts and icons to see them better when background is white. Buffering database previews to show faster the Library. Updated how RAM usage is computed and now show max memory. Added warnings when RAM usage is low. * Added measuring tool * fixed map not shown when closing visualization * Added measure text size setting, changed look and feel of point to point * Fixed measuring point not showing * Added fix for #1401 * Addressing #1407 * Export: Added colored OBJ options * fixed index_t not existing on focal * Fixed Settings not applied after restoring to all default settings witohut restarting the app (Marker detection not working issue #1455 ) * Marker detection: Fixing wrong depth used when rgb and depth image sizes cannot be divided exactly one from the the other #1455 * Added Marker Max Range option (default 1m) * Added OBJ texture policy option (keep color on textureless polygons) * Added texture/color blending option directly in the app. Added LAZ export option. * Hiding measuring button if not mesh, dont zip if exporting to laz, updating Export XXX button based on the current context, fixed always blending texture/color on not visualization mode * updated default marker max range to 2m * bump ios app version * fixing pcl 1.8.1 build * fixed android build
195 lines
7.5 KiB
Swift
195 lines
7.5 KiB
Swift
/**
|
||
* Copyright (c) 2017 Razeware LLC
|
||
*
|
||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
* of this software and associated documentation files (the "Software"), to deal
|
||
* in the Software without restriction, including without limitation the rights
|
||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
* copies of the Software, and to permit persons to whom the Software is
|
||
* furnished to do so, subject to the following conditions:
|
||
*
|
||
* The above copyright notice and this permission notice shall be included in
|
||
* all copies or substantial portions of the Software.
|
||
*
|
||
* Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
|
||
* distribute, sublicense, create a derivative work, and/or sell copies of the
|
||
* Software in any work that is designed, intended, or marketed for pedagogical or
|
||
* instructional purposes related to programming, coding, application development,
|
||
* or information technology. Permission for such use, copying, modification,
|
||
* merger, publication, distribution, sublicensing, creation of derivative works,
|
||
* or sale is expressly withheld.
|
||
*
|
||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||
* THE SOFTWARE.
|
||
*/
|
||
|
||
|
||
import UIKit
|
||
|
||
protocol DatabaseViewDelegate: class {
|
||
func databaseShared(databaseURL: URL)
|
||
func databaseRenamed(databaseURL: URL)
|
||
func databaseDeleted(databaseURL: URL)
|
||
}
|
||
|
||
class DatabaseView: UIView {
|
||
|
||
private var coverImageView: UIImageView!
|
||
private var indicatorView: UIActivityIndicatorView!
|
||
private var valueObservation: NSKeyValueObservation!
|
||
private var textLabel: UILabel!
|
||
private var databaseURL: URL!
|
||
public var delegate: DatabaseViewDelegate!
|
||
|
||
required init?(coder aDecoder: NSCoder) {
|
||
super.init(coder: aDecoder)
|
||
commonInit(databasePath: "NA")
|
||
}
|
||
|
||
init(frame: CGRect, databaseURL: URL) {
|
||
super.init(frame: frame)
|
||
self.databaseURL = databaseURL
|
||
commonInit(databasePath: databaseURL.path)
|
||
if let image = ViewController.previewImages[databaseURL.path]
|
||
{
|
||
self.coverImageView.image = image
|
||
}
|
||
else
|
||
{
|
||
DispatchQueue.global().async {
|
||
let downloadedImage = getPreviewImage(databasePath: databaseURL.path)
|
||
DispatchQueue.main.async {
|
||
self.coverImageView.image = downloadedImage
|
||
ViewController.previewImages[databaseURL.path] = downloadedImage
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private func commonInit(databasePath: String) {
|
||
|
||
// Setup the background
|
||
backgroundColor = .black
|
||
// Create the cover image view
|
||
coverImageView = UIImageView()
|
||
coverImageView.translatesAutoresizingMaskIntoConstraints = false
|
||
|
||
valueObservation = coverImageView.observe(\.image, options: [.new]) { [unowned self] observed, change in
|
||
if change.newValue is UIImage {
|
||
self.indicatorView.stopAnimating()
|
||
}
|
||
}
|
||
|
||
//Text Label
|
||
textLabel = UILabel()
|
||
textLabel.numberOfLines = 0
|
||
textLabel.text =
|
||
URL(fileURLWithPath: databasePath).lastPathComponent + "\n" +
|
||
URL(fileURLWithPath: databasePath).fileSizeString + "\n" +
|
||
(try! URL(fileURLWithPath: databasePath).resourceValues(forKeys: [.contentModificationDateKey]).contentModificationDate!.getFormattedDate(format: "yyyy-MM-dd HH:mm:ss"))
|
||
textLabel.textColor = .white
|
||
textLabel.textAlignment = .left
|
||
|
||
//Stack View
|
||
let stackView = UIStackView()
|
||
stackView.axis = NSLayoutConstraint.Axis.horizontal
|
||
stackView.distribution = UIStackView.Distribution.fill
|
||
stackView.alignment = UIStackView.Alignment.center
|
||
stackView.spacing = 8.0
|
||
|
||
stackView.addArrangedSubview(coverImageView)
|
||
stackView.addArrangedSubview(textLabel)
|
||
stackView.translatesAutoresizingMaskIntoConstraints = false
|
||
|
||
addSubview(stackView)
|
||
|
||
// Create the indicator view
|
||
indicatorView = UIActivityIndicatorView()
|
||
indicatorView.translatesAutoresizingMaskIntoConstraints = false
|
||
indicatorView.style = .whiteLarge
|
||
indicatorView.startAnimating()
|
||
addSubview(indicatorView)
|
||
|
||
NSLayoutConstraint.activate([
|
||
stackView.leftAnchor.constraint(equalTo: self.leftAnchor),
|
||
stackView.rightAnchor.constraint(equalTo: self.rightAnchor),
|
||
stackView.topAnchor.constraint(equalTo: self.topAnchor),
|
||
stackView.bottomAnchor.constraint(equalTo: self.bottomAnchor),
|
||
stackView.leadingAnchor.constraint(equalTo: self.leadingAnchor),
|
||
coverImageView.widthAnchor.constraint(equalToConstant: 180 - 5),
|
||
indicatorView.centerXAnchor.constraint(equalTo: coverImageView.centerXAnchor),
|
||
indicatorView.centerYAnchor.constraint(equalTo: coverImageView.centerYAnchor)
|
||
])
|
||
|
||
let interaction = UIContextMenuInteraction(delegate: self)
|
||
self.addInteraction(interaction)
|
||
}
|
||
|
||
func highlightDatabase(_ didHighlightView: Bool) {
|
||
if didHighlightView == true {
|
||
backgroundColor = .white
|
||
textLabel.textColor = .black
|
||
} else {
|
||
backgroundColor = .black
|
||
textLabel.textColor = .white
|
||
}
|
||
}
|
||
}
|
||
|
||
extension URL {
|
||
var attributes: [FileAttributeKey : Any]? {
|
||
do {
|
||
return try FileManager.default.attributesOfItem(atPath: path)
|
||
} catch let error as NSError {
|
||
print("FileAttribute error: \(error)")
|
||
}
|
||
return nil
|
||
}
|
||
|
||
var fileSize: UInt64 {
|
||
return attributes?[.size] as? UInt64 ?? UInt64(0)
|
||
}
|
||
|
||
var fileSizeString: String {
|
||
return ByteCountFormatter.string(fromByteCount: Int64(fileSize), countStyle: .file)
|
||
}
|
||
|
||
var creationDate: Date? {
|
||
return attributes?[.creationDate] as? Date
|
||
}
|
||
}
|
||
|
||
extension DatabaseView: UIContextMenuInteractionDelegate {
|
||
|
||
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
|
||
return UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { suggestedActions in
|
||
|
||
// Create an action for sharing
|
||
let share = UIAction(title: "Share", image: UIImage(systemName: "square.and.arrow.up")) { action in
|
||
// Show system share sheet
|
||
self.delegate?.databaseShared(databaseURL: self.databaseURL)
|
||
}
|
||
|
||
// Create an action for renaming
|
||
let rename = UIAction(title: "Rename", image: UIImage(systemName: "square.and.pencil")) { action in
|
||
// Perform renaming
|
||
self.delegate?.databaseRenamed(databaseURL: self.databaseURL)
|
||
}
|
||
|
||
// Here we specify the "destructive" attribute to show that it’s destructive in nature
|
||
let delete = UIAction(title: "Delete", image: UIImage(systemName: "trash"), attributes: .destructive) { action in
|
||
// Perform delete
|
||
self.delegate?.databaseDeleted(databaseURL: self.databaseURL)
|
||
}
|
||
|
||
// Create and return a UIMenu with all of the actions as children
|
||
return UIMenu(title: "", children: [share, rename, delete])
|
||
}
|
||
}
|
||
}
|