David PHAM-VAN

Improve macOS directPrint

@@ -160,15 +160,7 @@ class MethodChannelPrinting extends PrintingPlatform { @@ -160,15 +160,7 @@ class MethodChannelPrinting extends PrintingPlatform {
160 final printers = <Printer>[]; 160 final printers = <Printer>[];
161 161
162 for (final printer in list) { 162 for (final printer in list) {
163 - printers.add(Printer(  
164 - url: printer['url'],  
165 - name: printer['name'],  
166 - model: printer['model'],  
167 - location: printer['location'],  
168 - comment: printer['comment'],  
169 - isDefault: printer['default'],  
170 - available: printer['available'],  
171 - )); 163 + printers.add(Printer.fromMap(printer));
172 } 164 }
173 165
174 return printers; 166 return printers;
@@ -187,12 +179,7 @@ class MethodChannelPrinting extends PrintingPlatform { @@ -187,12 +179,7 @@ class MethodChannelPrinting extends PrintingPlatform {
187 if (printer == null) { 179 if (printer == null) {
188 return null; 180 return null;
189 } 181 }
190 - return Printer(  
191 - url: printer['url'],  
192 - name: printer['name'],  
193 - model: printer['model'],  
194 - location: printer['location'],  
195 - ); 182 + return Printer.fromMap(printer);
196 } 183 }
197 184
198 @override 185 @override
@@ -215,6 +202,12 @@ class MethodChannelPrinting extends PrintingPlatform { @@ -215,6 +202,12 @@ class MethodChannelPrinting extends PrintingPlatform {
215 'name': name, 202 'name': name,
216 'printer': printer.url, 203 'printer': printer.url,
217 'doc': bytes, 204 'doc': bytes,
  205 + 'width': format.width,
  206 + 'height': format.height,
  207 + 'marginLeft': format.marginLeft,
  208 + 'marginTop': format.marginTop,
  209 + 'marginRight': format.marginRight,
  210 + 'marginBottom': format.marginBottom,
218 'job': job.index, 211 'job': job.index,
219 }; 212 };
220 await _channel.invokeMethod<int>('directPrintPdf', params); 213 await _channel.invokeMethod<int>('directPrintPdf', params);
@@ -22,13 +22,27 @@ class Printer { @@ -22,13 +22,27 @@ class Printer {
22 /// Create a printer information 22 /// Create a printer information
23 const Printer({ 23 const Printer({
24 @required this.url, 24 @required this.url,
25 - this.name, 25 + String name,
26 this.model, 26 this.model,
27 this.location, 27 this.location,
28 this.comment, 28 this.comment,
29 - this.isDefault = false,  
30 - this.available = true,  
31 - }) : assert(url != null); 29 + bool isDefault,
  30 + bool isAvailable,
  31 + }) : assert(url != null),
  32 + name = name ?? url,
  33 + isDefault = isDefault ?? false,
  34 + isAvailable = isAvailable ?? true;
  35 +
  36 + /// Create an information object from a dictionnary
  37 + factory Printer.fromMap(Map<dynamic, dynamic> map) => Printer(
  38 + url: map['url'],
  39 + name: map['name'],
  40 + model: map['model'],
  41 + location: map['location'],
  42 + comment: map['comment'],
  43 + isDefault: map['default'],
  44 + isAvailable: map['available'],
  45 + );
32 46
33 /// The platform specific printer identification 47 /// The platform specific printer identification
34 final String url; 48 final String url;
@@ -49,8 +63,14 @@ class Printer { @@ -49,8 +63,14 @@ class Printer {
49 final bool isDefault; 63 final bool isDefault;
50 64
51 /// The printer is available for printing 65 /// The printer is available for printing
52 - final bool available; 66 + final bool isAvailable;
53 67
54 @override 68 @override
55 - String toString() => name ?? url; 69 + String toString() => '''$runtimeType $name
  70 + url:$url
  71 + location:$location
  72 + model:$model
  73 + comment:$comment
  74 + isDefault:$isDefault
  75 + isAvailable: $isAvailable''';
56 } 76 }
@@ -91,7 +91,7 @@ mixin Printing { @@ -91,7 +91,7 @@ mixin Printing {
91 title: Text(title ?? 'Select Printer'), 91 title: Text(title ?? 'Select Printer'),
92 children: [ 92 children: [
93 for (final printer in printers) 93 for (final printer in printers)
94 - if (printer.available) 94 + if (printer.isAvailable)
95 SimpleDialogOption( 95 SimpleDialogOption(
96 child: Text( 96 child: Text(
97 printer.name, 97 printer.name,
@@ -72,7 +72,7 @@ class PrintingInfo { @@ -72,7 +72,7 @@ class PrintingInfo {
72 final bool canRaster; 72 final bool canRaster;
73 73
74 @override 74 @override
75 - String toString() => '''PrintingInfo: 75 + String toString() => '''$runtimeType:
76 canPrint: $canPrint 76 canPrint: $canPrint
77 directPrint: $directPrint 77 directPrint: $directPrint
78 dynamicLayout: $dynamicLayout 78 dynamicLayout: $dynamicLayout
@@ -80,17 +80,4 @@ class PrintingInfo { @@ -80,17 +80,4 @@ class PrintingInfo {
80 canListPrinters: $canListPrinters 80 canListPrinters: $canListPrinters
81 canShare: $canShare 81 canShare: $canShare
82 canRaster: $canRaster'''; 82 canRaster: $canRaster''';
83 -  
84 - /// Returns a map representation of this object  
85 - Map<dynamic, dynamic> asMap() {  
86 - return <dynamic, dynamic>{  
87 - 'canPrint': canPrint,  
88 - 'directPrint': directPrint,  
89 - 'dynamicLayout': dynamicLayout,  
90 - 'canConvertHtml': canConvertHtml,  
91 - 'canListPrinters': canListPrinters,  
92 - 'canShare': canShare,  
93 - 'canRaster': canRaster,  
94 - };  
95 - }  
96 } 83 }
@@ -43,8 +43,10 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate { @@ -43,8 +43,10 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate {
43 43
44 // Return the number of pages available for printing 44 // Return the number of pages available for printing
45 override public func knowsPageRange(_ range: NSRangePointer) -> Bool { 45 override public func knowsPageRange(_ range: NSRangePointer) -> Bool {
46 - setFrameSize(printOperation!.printPanel.printInfo.paperSize)  
47 - setBoundsSize(printOperation!.printPanel.printInfo.paperSize) 46 + let size = printOperation!.showsPrintPanel ? printOperation!.printPanel.printInfo.paperSize : printOperation!.printInfo.paperSize
  47 +
  48 + setFrameSize(size)
  49 + setBoundsSize(size)
48 range.pointee.length = pdfDocument?.numberOfPages ?? 0 50 range.pointee.length = pdfDocument?.numberOfPages ?? 0
49 return true 51 return true
50 } 52 }
@@ -78,7 +80,47 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate { @@ -78,7 +80,47 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate {
78 } 80 }
79 } 81 }
80 82
81 - public func directPrintPdf(name _: String, data _: Data, withPrinter _: String) {} 83 + public func listPrinters() -> [NSDictionary] {
  84 + var printers: Array = [NSDictionary]()
  85 +
  86 + for name in NSPrinter.printerNames {
  87 + let printer = NSPrinter(name: name)
  88 + let pr: NSDictionary = [
  89 + "url": name,
  90 + "name": name,
  91 + "model": printer!.type,
  92 + ]
  93 + printers.append(pr)
  94 + }
  95 +
  96 + return printers
  97 + }
  98 +
  99 + public func directPrintPdf(name: String, data: Data, withPrinter printer: String, width: CGFloat, height: CGFloat) {
  100 + let sharedInfo = NSPrintInfo.shared
  101 + let sharedDict = sharedInfo.dictionary()
  102 + let printInfoDict = NSMutableDictionary(dictionary: sharedDict)
  103 + let printInfo = NSPrintInfo(dictionary: printInfoDict as! [NSPrintInfo.AttributeKey: Any])
  104 + printInfo.printer = NSPrinter(name: printer)!
  105 +
  106 + let bytesPointer = UnsafeMutablePointer<UInt8>.allocate(capacity: data.count)
  107 + data.copyBytes(to: bytesPointer, count: data.count)
  108 + let dataProvider = CGDataProvider(dataInfo: nil, data: bytesPointer, size: data.count, releaseData: dataProviderReleaseDataCallback)
  109 + pdfDocument = CGPDFDocument(dataProvider!)
  110 + printInfo.paperSize = NSSize(width: width, height: height)
  111 + if width > height {
  112 + printInfo.orientation = NSPrintInfo.PaperOrientation.landscape
  113 + }
  114 +
  115 + // Print the custom view
  116 + printOperation = NSPrintOperation(view: self, printInfo: printInfo)
  117 + printOperation!.jobTitle = name
  118 + printOperation!.showsPrintPanel = false
  119 + printOperation!.showsProgressPanel = false
  120 +
  121 + let window = NSApplication.shared.mainWindow!
  122 + printOperation!.runModal(for: window, delegate: self, didRun: #selector(printOperationDidRun(printOperation:success:contextInfo:)), contextInfo: nil)
  123 + }
82 124
83 public func printPdf(name: String, withPageSize size: CGSize, andMargin _: CGRect) { 125 public func printPdf(name: String, withPageSize size: CGSize, andMargin _: CGRect) {
84 let sharedInfo = NSPrintInfo.shared 126 let sharedInfo = NSPrintInfo.shared
@@ -86,6 +128,7 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate { @@ -86,6 +128,7 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate {
86 let printInfoDict = NSMutableDictionary(dictionary: sharedDict) 128 let printInfoDict = NSMutableDictionary(dictionary: sharedDict)
87 let printInfo = NSPrintInfo(dictionary: printInfoDict as! [NSPrintInfo.AttributeKey: Any]) 129 let printInfo = NSPrintInfo(dictionary: printInfoDict as! [NSPrintInfo.AttributeKey: Any])
88 130
  131 + printInfo.paperSize = size
89 if size.width > size.height { 132 if size.width > size.height {
90 printInfo.orientation = NSPrintInfo.PaperOrientation.landscape 133 printInfo.orientation = NSPrintInfo.PaperOrientation.landscape
91 } 134 }
@@ -171,10 +214,6 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate { @@ -171,10 +214,6 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate {
171 } 214 }
172 } 215 }
173 216
174 - public static func pickPrinter(result: @escaping FlutterResult, withSourceRect _: CGRect) {  
175 - result(NSNumber(value: 1))  
176 - }  
177 -  
178 public func rasterPdf(data: Data, pages: [Int]?, scale: CGFloat) { 217 public func rasterPdf(data: Data, pages: [Int]?, scale: CGFloat) {
179 let provider = CGDataProvider(data: data as CFData)! 218 let provider = CGDataProvider(data: data as CFData)!
180 let document = CGPDFDocument(provider)! 219 let document = CGPDFDocument(provider)!
@@ -220,12 +259,13 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate { @@ -220,12 +259,13 @@ public class PrintJob: NSView, NSSharingServicePickerDelegate {
220 259
221 public static func printingInfo() -> NSDictionary { 260 public static func printingInfo() -> NSDictionary {
222 let data: NSDictionary = [ 261 let data: NSDictionary = [
223 - "directPrint": false, 262 + "directPrint": true,
224 "dynamicLayout": false, 263 "dynamicLayout": false,
225 "canPrint": true, 264 "canPrint": true,
226 "canConvertHtml": true, 265 "canConvertHtml": true,
227 "canShare": true, 266 "canShare": true,
228 "canRaster": true, 267 "canRaster": true,
  268 + "canListPrinters": true,
229 ] 269 ]
230 return data 270 return data
231 } 271 }
@@ -56,13 +56,19 @@ public class PrintingPlugin: NSObject, FlutterPlugin { @@ -56,13 +56,19 @@ public class PrintingPlugin: NSObject, FlutterPlugin {
56 height: height - marginBottom - marginTop 56 height: height - marginBottom - marginTop
57 )) 57 ))
58 result(NSNumber(value: 1)) 58 result(NSNumber(value: 1))
59 -// } else if call.method == "directPrintPdf" {  
60 -// let name = args["name"] as! String  
61 -// let printer = args["printer"] as! String  
62 -// let object = args["doc"] as! FlutterStandardTypedData  
63 -// let printJob = PrintJob(printing: self, index: args["job"] as! Int)  
64 -// printJob.directPrintPdf(name: name, data: object.data, withPrinter: printer)  
65 -// result(NSNumber(value: 1)) 59 + } else if call.method == "listPrinters" {
  60 + let printJob = PrintJob(printing: self, index: -1)
  61 + let r = printJob.listPrinters()
  62 + result(r)
  63 + } else if call.method == "directPrintPdf" {
  64 + let name = args["name"] as! String
  65 + let printer = args["printer"] as! String
  66 + let object = args["doc"] as! FlutterStandardTypedData
  67 + let width = CGFloat((args["width"] as? NSNumber)?.floatValue ?? 0.0)
  68 + let height = CGFloat((args["height"] as? NSNumber)?.floatValue ?? 0.0)
  69 + let printJob = PrintJob(printing: self, index: args["job"] as! Int)
  70 + printJob.directPrintPdf(name: name, data: object.data, withPrinter: printer, width: width, height: height)
  71 + result(NSNumber(1))
66 } else if call.method == "sharePdf" { 72 } else if call.method == "sharePdf" {
67 let object = args["doc"] as! FlutterStandardTypedData 73 let object = args["doc"] as! FlutterStandardTypedData
68 PrintJob.sharePdf( 74 PrintJob.sharePdf(