Honeycombs: Difference between revisions
Content added Content deleted
Alpha bravo (talk | contribs) (Added AutoHotkey) |
|||
Line 2,398: | Line 2,398: | ||
End Function |
End Function |
||
</lang> |
</lang> |
||
=={{header|Nim}}== |
|||
{{libheader|gintro}} |
|||
This program is largely inspired by the C version, but this is not a direct translation. We have reused many parts of the C version, for instance the computations and the way to draw the cells. But we have also introduced a “honeycomb” object, improved somewhat the drawing of the labels and taken advantage of the high level binding to Gtk3 provided by “gintro”. |
|||
<lang Nim>import lenientops, math, random, sequtils, strutils, tables |
|||
import gintro/[gobject, gdk, gtk, gio, cairo] |
|||
import gintro/glib except PI |
|||
const |
|||
Size = 308 # Size of drawing area. |
|||
NHexagons = 20 # Number of hexagons. |
|||
Radius = 30.0 |
|||
XOffset = 1 + sin(PI / 6) |
|||
YOffset = cos(PI / 6) |
|||
type |
|||
Letter = range['A'..'Z'] |
|||
# Description of a hexagon. |
|||
Hexagon = object |
|||
cx, cy: float |
|||
letter: Letter |
|||
selected: bool |
|||
# Description of the honeycomb. |
|||
HoneyComb = ref object |
|||
hexagons: array[NHexagons, Hexagon] # List of hexagons. |
|||
indexes: tables.Table[char, int] # Mapping letter -> index of hexagon. |
|||
archive: seq[Letter] # List of selected letters. |
|||
label: Label # Label displaying the selected letters. |
|||
#--------------------------------------------------------------------------------------------------- |
|||
proc newHoneyComb(): HoneyComb = |
|||
## Create a honeycomb. |
|||
new(result) |
|||
var letters = toSeq('A'..'Z') |
|||
letters.shuffle() |
|||
for i in 0..<NHexagons: |
|||
result.hexagons[i].letter = letters[i] |
|||
result.indexes[letters[i]] = i |
|||
# Compute position of hexagon center. |
|||
let q = i div 4 |
|||
let m = i mod 4 |
|||
result.hexagons[i].cx = Radius * (2 + q * XOffset) |
|||
result.hexagons[i].cy = Radius * (2 * (1 + m * YOffset) + (q and 1) * YOffset) |
|||
#--------------------------------------------------------------------------------------------------- |
|||
proc drawHexagons(context: Context; honeyComb: HoneyComb; select: bool) = |
|||
## Draw a hexagon (content or border). |
|||
for hex in honeyComb.hexagons: |
|||
if select == hex.selected: |
|||
let cx = hex.cx |
|||
let cy = hex.cy |
|||
context.moveTo(cx + Radius, cy) |
|||
for i in 1..5: |
|||
let x = cx + Radius * cos(i * PI / 3) |
|||
let y = cy + Radius * sin(i * PI / 3) |
|||
context.lineTo(x, y) |
|||
#--------------------------------------------------------------------------------------------------- |
|||
proc drawLabels(context: Context; honeyComb: HoneyComb; select: bool) = |
|||
## Draw the labels of the hexagons. |
|||
for hex in honeyComb.hexagons: |
|||
if select == hex.selected: |
|||
let letter = $hex.letter |
|||
var extents: TextExtents # Used to adjust letter position in hexagon. |
|||
context.getTextExtents(letter, extents) |
|||
context.moveTo(hex.cx - extents.width / 2, hex.cy + extents.height / 2) |
|||
context.showText(letter) |
|||
#--------------------------------------------------------------------------------------------------- |
|||
proc onDraw(area: DrawingArea; context: Context; honeyComb: HoneyComb): bool = |
|||
## Callback to draw/redraw the drawing area contents. |
|||
# Fill unselected in yellow. |
|||
context.setSource(0.8, 0.8, 0.0, 1.0) |
|||
context.drawHexagons(honeyComb, false) |
|||
context.fill() |
|||
# Fill selected in purple. |
|||
context.setSource(0.8, 0.0, 0.8, 1.0) |
|||
context.drawHexagons(honeyComb, true) |
|||
context.fill() |
|||
# Draw border. |
|||
context.setLineWidth(3.0) |
|||
context.setSource(0.7, 0.7, 0.7, 0.7) |
|||
context.drawHexagons(honeyComb, false) |
|||
context.stroke() |
|||
# Prepare label drawing. |
|||
context.selectFontFace("cairo:monospace", FontSlant.normal, FontWeight.bold) |
|||
context.setFontSize(14.0) |
|||
# Draw labels for selected hexagons. |
|||
context.setSource(0, 0, 0, 1) |
|||
context.drawLabels(honeyComb, true) |
|||
context.stroke() |
|||
# Draw labels for unselected hexagons. |
|||
context.setSource(0, 0, 1, 1) |
|||
context.drawLabels(honeyComb, false) |
|||
context.stroke() |
|||
result = true |
|||
#--------------------------------------------------------------------------------------------------- |
|||
proc select(honeyComb: HoneyComb; hex: var Hexagon) = |
|||
## Select a hexagon. |
|||
hex.selected = true |
|||
honeyComb.archive.add(hex.letter) |
|||
honeyComb.label.setText(honeyComb.label.text() & hex.letter) |
|||
#--------------------------------------------------------------------------------------------------- |
|||
proc onButtonPress(area: DrawingArea; event: Event; honeyComb: HoneyComb): bool = |
|||
## Callback to process a button press event. |
|||
var xwin, ywin: float |
|||
if not event.getCoords(xwin, ywin): return false |
|||
# Search the hexagon selected. |
|||
for hex in honeyComb.hexagons.mitems: |
|||
if hypot(xwin - hex.cx, ywin - hex.cy) < Radius * cos(PI / 15): |
|||
if not hex.selected: |
|||
honeyComb.select(hex) |
|||
area.window().invalidateRect() |
|||
break |
|||
return true |
|||
#--------------------------------------------------------------------------------------------------- |
|||
proc onKeyPress(area: DrawingArea; event: Event; honeyComb: HoneyComb): bool = |
|||
## Callbakc to process a key press event. |
|||
var keyval: int |
|||
if not event.getKeyval(keyval): return false |
|||
if keyval notin ord('a')..ord('z'): return false # For ASCII letters, keyvals are ASCII codes. |
|||
let letter = chr(keyval).toUpperAscii() # We want the uppercase letter. |
|||
if letter notin honeyComb.indexes: return false |
|||
let idx = honeyComb.indexes[letter] |
|||
if not honeyComb.hexagons[idx].selected: |
|||
honeyComb.select(honeyComb.hexagons[idx]) |
|||
area.window().invalidateRect() |
|||
#--------------------------------------------------------------------------------------------------- |
|||
proc activate(app: Application) = |
|||
## Activate the application. |
|||
var honeyComb = newHoneyComb() |
|||
let window = app.newApplicationWindow() |
|||
window.setTitle("Honeycombs") |
|||
let vbox = newBox(Orientation.vertical, 1) |
|||
window.add(vbox) |
|||
honeyComb.label = newLabel() |
|||
vbox.packEnd(honeyComb.label, false, false, 4) |
|||
# Create the drawing area. |
|||
let area = newDrawingArea() |
|||
area.setEvents({EventFlag.buttonPress, EventFlag.keyPress, EventFlag.exposure}) |
|||
vbox.packStart(area, true, true, 4) |
|||
area.setSizeRequest(Size, Size) |
|||
area.setCanFocus(true) |
|||
# Connect events. |
|||
discard area.connect("draw", ondraw, honeyComb) |
|||
discard area.connect("button-press-event", onButtonPress, honeyComb) |
|||
discard area.connect("key-press-event", onKeyPress, honeyComb) |
|||
window.showAll() |
|||
#——————————————————————————————————————————————————————————————————————————————————————————————————— |
|||
randomize() |
|||
let app = newApplication(Application, "Rosetta.honeycombs") |
|||
discard app.connect("activate", activate) |
|||
discard app.run()</lang> |
|||
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
=={{header|Mathematica}} / {{header|Wolfram Language}}== |