I am starting with Scala and with ScalaFX, I understand most of the code but I don't understand this code using for the examples in ScalaFx;
where instantiate an anonymous class follow it by curly braces, How this works???
object ScalaFXHelloWorld extends JFXApp {
stage = new PrimaryStage {
title = "ScalaFX Hello World"
scene = new Scene {
fill = Black
content = new HBox {
padding = Insets(20)
children = Seq(
new Text {
text = "Hello"
style = "-fx-font-size: 48pt"
fill = new LinearGradient(
endX = 0,
stops = Stops(PaleGreen, SeaGreen)
)
},
new Text {
text = "World!!!"
style = "-fx-font-size: 48pt"
fill = new LinearGradient(
endX = 0,
stops = Stops(Cyan, DodgerBlue)
)
effect = new DropShadow {
color = DodgerBlue
radius = 25
spread = 0.25
}
}
)
}
}
}
}
the part I don't understand is why in the creation of an anonymous class is follow by curly braces (with some more declarations)(Scene is not a trail to be filling the abstract parts of that class) and even fill or content are functions not a variables and Black for fill for instant is a val meaning that this line
fill = Black
is doing calling a function fill and assigning a val to it(don't make sense for me ), this is fill definition
def fill: ObjectProperty[jfxsp.Paint] = delegate.fillProperty
and this is Black
val Black = new Color(jfxsp.Color.BLACK)
how works this instantiation of a new object with curly braces please help, want to understand.
This is because ScalaFx is wrapping JavaFx and something special is going on here?.
Thank you guys.
Update:
Well now I know that it is calling a setter via syntax sugar however I check that setter and I don't understand what is going on there
Check it out:
def fill: ObjectProperty[jfxsp.Paint] = delegate.fillProperty
def fill_=(v: Paint) {
fill() = v
}
how come the setter is calling the getter to update the value?
delegate.fillProperty
is a function that return a value
The syntax for anonymous classes in Scala is borrowed from Java; you can see it here, too:
class Coder {
protected String name;
public Coder(String name) {this.name = name;}
}
public static void main(String[] args) {
// Prints "Mr. Noble"
new Coder("Noble") {
private String prefix = "Mr.";
{
System.out.println(prefix + " " + name);
}
}
}
Because Scala lets you write your constructor code in the class body, all of your x = y statements are executed when you instantiate those anonymous classes. As #resueman points out, these are actually getters and setters in this format:
class Scene {
var _fill
def fill_=(color: Color) // Setter, has some hidden logic to set up the UI
def fill = _fill // Getter
}
And your statement fill = Black is desugared to fill_=(Black).
Related
I want to create a Mapbox IControl object, which zooms the map in when a button in the control is clicked.
This is my custom IControl class:
class customControl {
_map;
_container;
_myButton;
constructor() {
this._myButton = document.createElement('button');
this._myButton.className = 'mapboxgl-ctrl-zoom-in';
this._myButton.type = 'button';
this._myButton.title = 'Test';
this._myButton.onclick = this._myAction;
this._container = document.createElement('div');
this._container.className = 'mapboxgl-ctrl-group mapboxgl-ctrl';
this._container.appendChild(this._myButton);
}
onAdd(map) {
this._map = map;
return this._container;
}
onRemove() {
this._container.parentNode.removeChild(this._container);
this._map = undefined;
}
_myAction() {
const map = this._map;
console.log(this._map);
map.zoomIn();
}
}
I add this control to my map using the following code:
let myControl = new customControl();
map.addControl(myControl, 'bottom-left');
When the button is clicked, I however get an Cannot read properties of undefined (reading 'zoomIn') error message, since this._map is obviously undefined. When I remove the const map = this._map; line from the _myAction() function, the zoom in works as expected, but the global map object is used.
Why is this._map undefined in _myAction()? Is there a way to make _myAction() aware of the "scope" the button is clicked, so I can access properties of my custom IControl when clicked?
I am using barcodewriter to write datamatrix barcoe. While most of the times it creates correct square style datamatrix barcode, for some of text it creates rectangular shaped barcode.
For inputData like below it creates rectangular barcode
8004600000070000017
C/TH PAUL PENGELLY
C/TH NICKY PARSONS
C/TH ROSEMARIE BARTOLOME
while for others it creates square styled: CTH HEKT-WOODROW MORGAN
800460000007
800460000007000001700000
i am usinf this code to generate code:
BarcodeWriter writer = new BarcodeWriter() { Format = BarcodeFormat.DATA_MATRIX };
var img = writer.Write(inputData);
return new Bitmap(img);
img.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
dto.BarcodeImage = ms.ToArray();
How can I make sure that I always get Square shaped datamatrix?
I have alread tried adding height,width options.
Thanks
There is SymbolShape option which can be used to force shape .
DatamatrixEncodingOptions options = new DatamatrixEncodingOptions()
{
Height = 300,
Width = 300,
PureBarcode = true,
Margin = 1,
SymbolShape = SymbolShapeHint.FORCE_SQUARE
};
It is not easy to detect but after careful reviewing, I found how to do it.
readonly DataMatrixWriter DMencoder = new();
readonly Dictionary<EncodeHintType, object> DMencodeType = new()
{
[EncodeHintType.DATA_MATRIX_DEFAULT_ENCODATION] = Encodation.C40, //Optional
[EncodeHintType.DATA_MATRIX_SHAPE] = SymbolShapeHint.FORCE_SQUARE
};
DMencoder.encode(matrixText, BarcodeFormat.DATA_MATRIX, 100, 100, DMencodeType)
Here is an example from Pro ScalaFX:
package proscalafx.ch02.stagecoach
import scalafx.Includes._
import scalafx.application.JFXApp
import scalafx.application.JFXApp.PrimaryStage
import scalafx.beans.property.StringProperty
import scalafx.geometry.VPos
import scalafx.scene.control.{Button, CheckBox, Label, TextField}
import scalafx.scene.input.MouseEvent
import scalafx.scene.layout.{HBox, VBox}
import scalafx.scene.paint.Color
import scalafx.scene.shape.Rectangle
import scalafx.scene.text.Text
import scalafx.scene.{Group, Scene}
import scalafx.stage.{Screen, StageStyle}
/** Stage property example.
*
* Can be run with various command line parameters to control stage style:
* decorated - a solid white background and platform decorations (default).
* transparent - transparent background and no decorations.
* undecorated - a solid white background and no decorations.
* utility - a solid white background and minimal platform decorations used for a utility window.
* #author Rafael
*/
object StageCoachMain extends JFXApp {
val titleProperty = StringProperty("")
// Process command line parameters
val stageStyle = parameters.unnamed match {
case Seq("transparent") => StageStyle.TRANSPARENT
case Seq("undecorated") => StageStyle.UNDECORATED
case Seq("utility") => StageStyle.UTILITY
case _ => StageStyle.DECORATED
}
lazy val textStageX = new Text {
textOrigin = VPos.Top
}
lazy val textStageY = new Text {
textOrigin = VPos.Top
}
lazy val textStageW = new Text {
textOrigin = VPos.Top
}
lazy val textStageH = new Text {
textOrigin = VPos.Top
}
lazy val textStageF = new Text {
textOrigin = VPos.Top
}
lazy val checkBoxResizable = new CheckBox {
text = "resizable"
// disable = stageStyle == StageStyle.TRANSPARENT || stageStyle == StageStyle.UNDECORATED
}
lazy val checkBoxFullScreen = new CheckBox {
text = "fullScreen"
}
lazy val titleTextField = new TextField {
text = "Stage Coach"
prefColumnCount = 15
}
stage = new PrimaryStage {
resizable = false
title <== titleProperty
scene = new Scene(370, 370) {
fill = Color.Transparent
root = new Group {
children = List(
new Rectangle {
width = 350
height = 350
arcWidth = 50
arcHeight = 50
fill = Color.SkyBlue
},
new VBox {
layoutX = 30
layoutY = 20
spacing = 10
children = List(
textStageX,
textStageY,
textStageW,
textStageH,
textStageF,
checkBoxResizable,
checkBoxFullScreen,
new HBox {
spacing = 10
children = List(
new Label("title:"),
titleTextField)
},
new Button {
text = "toBack()"
onAction = handle {stage.toBack()}
},
new Button {
text = "toFront()"
onAction = handle {stage.toFront()}
},
new Button {
text = "close()"
onAction = handle {stage.close()}
}
)
}
)
}
}
}
//when mouse button is pressed, save the initial position of screen
val rootGroup = stage.scene().content(0)
var dragAnchorX = 0.0
var dragAnchorY = 0.0
rootGroup.onMousePressed = (me: MouseEvent) => {
dragAnchorX = me.screenX - stage.x.value
dragAnchorY = me.screenY - stage.y.value
}
rootGroup.onMouseDragged = (me: MouseEvent) => {
stage.x = me.screenX - dragAnchorX
stage.y = me.screenY - dragAnchorY
}
textStageX.text <== new StringProperty("x: ") + stage.x.asString
textStageY.text <== new StringProperty("y: ") + stage.y.asString
textStageW.text <== new StringProperty("width: ") + stage.width.asString
textStageH.text <== new StringProperty("height: ") + stage.height.asString
textStageF.text <== new StringProperty("focused: ") + stage.focused.asString
stage.resizable = false
// NOTE: Due to a bug in JavaFX (2.2.3+) Stage.resizableProperty(), cannot directly use binding here,
// see http://javafx-jira.kenai.com/browse/RT-25942
// TODO: Revert to binding once JavaFX bug is corrected
// stage.resizable <==> checkBoxResizable.selected
checkBoxResizable.selected.onChange {
// To avoid using resizableProperty, use delegate.setResizable()
// stage.resizable = checkBoxResizable.selected.get
stage.delegate.setResizable(checkBoxResizable.selected())
}
checkBoxFullScreen.onAction = handle {
stage.fullScreen = checkBoxFullScreen.selected()
}
stage.title <== titleTextField.text
stage.initStyle(stageStyle)
stage.onCloseRequest = handle {println("Stage is closing")}
val primScreenBounds = Screen.primary.visualBounds
stage.x = (primScreenBounds.width - stage.width()) / 2
stage.y = (primScreenBounds.height - stage.height()) / 2
}
If I remove lazy before these Text objects, the app seems to works exactly the same as before. For example the textStageX object should show x-coordinate of the stage in real-time, and it still does without being lazy. So, what purpose does lazy serve here?
Another problem is that these lines of code
val primScreenBounds = Screen.primary.visualBounds
stage.x = (primScreenBounds.width - stage.width()) / 2
stage.y = (primScreenBounds.height - stage.height()) / 2
seems to intend to place the window at the center of the primary screen, but fails to do so (on OS X 10.10, with Java 1.8 and Scala 2.11.7).
lazy in unnecessary here. It is used in JFXApp if there are initialization order issues.
For the centering to work. The stage has to be shown first. I am not sure it this new in JavaFX 8 or there was a bug in original StageCoachMain code. Just add:
stage.show()
before the last three lines. You can also replace them with simply:
stage.centerOnScreen()
Thanks for pointing this out. I cleaned up the code in ProScalaFX repo.
I have underlined "Some text" by
var par = new Paragraph();
par.Add(new Chunk("Some text", CreateFont(12, Font.UNDERLINE)));
document.Add(par);
It is possible underline just "Some text" with dashed line (not the paragraph)?
Thanks
This answer tells you how to do it but unfortunately doesn't provide any code so I've provided it below.
To the best on my knowledge there isn't a direct way to achieve this in iTextSharp by just setting a simple property. Instead, you need to use a PageEvent and manually draw the line yourself.
First you need to subclass PdfPageEventHelper:
private class UnderlineMaker : PdfPageEventHelper {
}
You then want to override the OnGenericTag() method:
public override void OnGenericTag(PdfWriter writer, Document document, iTextSharp.text.Rectangle rect, string text) {
}
The text variable will hold an arbitrary value that you set later on. Here's a full working example with comments:
private class UnderlineMaker : PdfPageEventHelper {
public override void OnGenericTag(PdfWriter writer, Document document, iTextSharp.text.Rectangle rect, string text) {
switch (text) {
case "dashed":
//Grab the canvas underneath the content
var cb = writer.DirectContentUnder;
//Save the current state so that we don't affect future canvas drawings
cb.SaveState();
//Set a line color
cb.SetColorStroke(BaseColor.BLUE);
//Set a dashes
//See this for more details: http://api.itextpdf.com/itext/com/itextpdf/text/pdf/PdfContentByte.html#setLineDash(float)
cb.SetLineDash(3, 2);
//Move the cursor to the left edge with the "pen up"
cb.MoveTo(rect.Left, rect.Bottom);
//Move to cursor to the right edge with the "pen down"
cb.LineTo(rect.Right, rect.Bottom);
//Actually draw the lines (the "pen downs")
cb.Stroke();
//Reset the drawing states to what it was before we started messing with it
cb.RestoreState();
break;
}
//There isn't actually anything here but I always just make it a habit to call my base
base.OnGenericTag(writer, document, rect, text);
}
}
And below is an implementation of it:
//Create a test file on the desktop
var testFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test.pdf");
//Normal iTextSharp boilerplate, nothing special here
using (var fs = new FileStream(testFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, fs)) {
doc.Open();
//Bind our helper class
writer.PageEvent = new UnderlineMaker();
//Create a new paragraph
var p = new Paragraph();
//Add a normal chunk
p.Add(new Chunk("This is a "));
//Create another chunk with an arbitrary tag associated with it and add to the paragraph
var c = new Chunk("dashed underline test");
c.SetGenericTag("dashed");
p.Add(c);
//Add the paragraph to the document
doc.Add(p);
doc.Close();
}
}
}
If you wanted to get fancy you could pass a delimited string to SetGenericTag() like dashed-black-2x4 or something and parse that out in the OnGenericTag event.
I'm trying to set up the update loop of a simple game, built with observables in mind. The top-level components are a model, which takes input commands, and produces updates; and a view, which displays the received updates, and produces input. In isolation, both work fine, the problematic part is putting the two together, since both depend on the other.
With the components being simplified to the following:
var view = function (updates) {
return Rx.Observable.fromArray([1,2,3]);
};
var model = function (inputs) {
return inputs.map(function (i) { return i * 10; });
};
The way I've hooked things together is this:
var inputBuffer = new Rx.Subject();
var updates = model(inputBuffer);
var inputs = view(updates);
updates.subscribe(
function (i) { console.log(i); },
function (e) { console.log("Error: " + e); },
function () { console.log("Completed"); }
);
inputs.subscribe(inputBuffer);
That is, I add a subject as a placeholder for the input stream, and attach the model to that. Then, after the view is constructed, I pass on the actual inputs to the placeholder subject, thus closing the loop.
I can't help but feel this is not the proper way to do things, however. Using a subject for this seems to be overkill. Is there a way to do the same thing with publish() or defer() or something along those lines?
UPDATE: Here's a less abstract example to illustrate what I'm having problems with. Below you see the code for a simple "game", where the player needs to click on a target to hit it. The target can either appear on the left or on the right, and whenever it is hit, it switches to the other side. Seems simple enough, but I still have the feeling I'm missing something...
//-- Helper methods and whatnot
// Variables to easily represent the two states of the target
var left = 'left';
var right = 'right';
// Transition from one side to the other
var flip = function (side) {
if (side === left) {
return right;
} else {
return left;
}
};
// Creates a predicate used for hit testing in the view
var nearby = function (target, radius) {
return function (position) {
var min = target - radius;
var max = target + radius;
return position >= min && position <= max;
};
};
// Same as Observable.prototype.scan, but it also yields the initial value immediately.
var initScan = function (values, init, updater) {
var initValue = Rx.Observable.return(init);
var restValues = values.scan(init, updater);
return initValue.concat(restValues);
};
//-- Part 1: From input to state --
var process = function (inputs) {
// Determine new state based on current state and input
var update = function(current, input) {
// Input value ignored here because there's only one possible state transition
return flip(current);
};
return initScan(inputs, left, update);
};
//-- Part 2: From display to inputs --
var display = function (states) {
// Simulate clicks from the user at various positions (only one dimension, for simplicity)
var clicks = Rx.Observable.interval(800)
.map(function (v) {return (v * 5) % 30; })
.do(function (v) { console.log("Shooting at: " + v)})
.publish();
clicks.connect();
// Display position of target depending on the model
var targetPos = states.map(function (state) {
return state === left ? 5 : 25;
});
// Determine which clicks are hits based on displayed position
return targetPos.flatMapLatest(function (target) {
return clicks
.filter(nearby(target, 10))
.map(function (pos) { return "HIT! (# "+ pos +")"; })
.do(console.log);
});
};
//-- Part 3: Putting the loop together
/**
* Creates the following feedback loop:
* - Commands are passed to the process function to generate updates.
* - Updates are passed to the display function to generates further commands.
* - (this closes the loop)
*/
var feedback = function (process, display) {
var inputBuffer = new Rx.Subject(),
updates = process(inputBuffer),
inputs = display(updates);
inputs.subscribe(inputBuffer);
};
feedback(process, display);
I think I understand what you are trying to achieve here:
How can I get a sequence of input events going in one direction that feed into a model
But have a sequence of output events going in the other direction that feed from the model to the view
I believe the answer here is that you probably want to flip your design. Assuming an MVVM style design, instead of having the Model know about the input sequence, it becomes agnostic. This means that you now have a model that has a InputRecieved/OnInput/ExecuteCommand method that the View will call with the input values. This should now be a lot easier for you to deal with a "Commands in one direction" and "Events in the other direction" pattern. A sort of tip-of-the-hat to CQRS here.
We use that style extensively on Views+Models in WPF/Silverlight/JS for the last 4 years.
Maybe something like this;
var model = function()
{
var self = this;
self.output = //Create observable sequence here
self.filter = function(input) {
//peform some command with input here
};
}
var viewModel = function (model) {
var self = this;
self.filterText = ko.observable('');
self.items = ko.observableArray();
self.filterText.subscribe(function(newFilterText) {
model.filter(newFilterText);
});
model.output.subscribe(item=>items.push(item));
};
update
Thanks for posting a full sample. It looks good. I like your new initScan operator, seems an obvious omission from Rx.
I took your code an restructured it the way I probably would have written it. I hope it help. The main things I did was encapsulted the logic into the model (flip, nearby etc) and have the view take the model as a parameter. Then I did also have to add some members to the model instead of it just being an observable sequence. This did however allow me to remove some extra logic from the view and put it in the model too (Hit logic)
//-- Helper methods and whatnot
// Same as Observable.prototype.scan, but it also yields the initial value immediately.
var initScan = function (values, init, updater) {
var initValue = Rx.Observable.return(init);
var restValues = values.scan(init, updater);
return initValue.concat(restValues);
};
//-- Part 1: From input to state --
var process = function () {
var self = this;
var shots = new Rx.Subject();
// Variables to easily represent the two states of the target
var left = 'left';
var right = 'right';
// Transition from one side to the other
var flip = function (side) {
if (side === left) {
return right;
} else {
return left;
}
};
// Determine new state based on current state and input
var update = function(current, input) {
// Input value ignored here because there's only one possible state transition
return flip(current);
};
// Creates a predicate used for hit testing in the view
var isNearby = function (target, radius) {
return function (position) {
var min = target - radius;
var max = target + radius;
return position >= min && position <= max;
};
};
self.shoot = function(input) {
shots.onNext(input);
};
self.positions = initScan(shots, left, update).map(function (state) {
return state === left ? 5 : 25;
});
self.hits = self.positions.flatMapLatest(function (target) {
return shots.filter(isNearby(target, 10));
});
};
//-- Part 2: From display to inputs --
var display = function (model) {
// Simulate clicks from the user at various positions (only one dimension, for simplicity)
var clicks = Rx.Observable.interval(800)
.map(function (v) {return (v * 5) % 30; })
.do(function (v) { console.log("Shooting at: " + v)})
.publish();
clicks.connect();
model.hits.subscribe(function(pos)=>{console.log("HIT! (# "+ pos +")");});
// Determine which clicks are hits based on displayed position
model.positions(function (target) {
return clicks
.subscribe(pos=>{
console.log("Shooting at " + pos + ")");
model.shoot(pos)
});
});
};
//-- Part 3: Putting the loop together
/**
* Creates the following feedback loop:
* - Commands are passed to the process function to generate updates.
* - Updates are passed to the display function to generates further commands.
* - (this closes the loop)
*/
var feedback = function (process, display) {
var model = process();
var view = display(model);
};
feedback(process, display);
I presume that because you do not "assign" the inputs after the model is created, you are aiming for a non-mutative approach to instantiating your model and view. However, your model and your view seem to depend on one another. To resolve this issue, you can use a third party to facilitate the relationship between the two objects. In this case, you can simply use a function for dependency injection...
var log = console.log.bind(console),
logError = console.log.bind(console, 'Error:'),
logCompleted = console.log.bind(console, 'Completed.'),
model(
function (updates) {
return view(updates);
}
)
.subscribe(
log,
logError,
logCompleted
);
By providing the model a factory to create a view, you give the model the ability to fully instantiate itself by instantiating it's view, but without knowing how the view is instantiated.
As per my comment on the question itself, here's the same sort of code you're writing done with a scheduler in Windows. I would expect a similar interface in RxJS.
var scheduler = new EventLoopScheduler();
var subscription = scheduler.Schedule(
new int[] { 1, 2, 3 },
TimeSpan.FromSeconds(1.0),
(xs, a) => a(
xs
.Do(x => Console.WriteLine(x))
.Select(x => x * 10)
.ToArray(),
TimeSpan.FromSeconds(1.0)));
The output I get, with three new numbers every second, is:
1
2
3
10
20
30
100
200
300
1000
2000
3000
10000
20000
30000