Files
kniip/.cursor/plans/emoji_stempel-tool_8dbf6487.plan.md
T
2026-11-07 12:19:45 +01:00

7.5 KiB

name, overview, todos, isProject
name overview todos isProject
Emoji stempel-tool Voeg een Emoji-gereedschap toe aan de werkbalk van de editor. Je plaatst er een Twemoji-stempel mee op het knipsel. De kiezer werkt zoals emoji-mart: alle emoji, categorie-tabs, zoeken in het Nederlands en Engels, huidskleur en "recent gebruikt".
id content status
assets Script tools/fetch-emoji.ps1 en Assets/Emoji (emoji.json, twemoji-64.png, cldr-nl.json) toevoegen als Resource in csproj completed
id content status
catalog EmojiCatalog: json/CLDR parsen, sheet croppen met cache, categorieën, zoeken, huidskleurvarianten completed
id content status
model ToolKind.Emoji, SkinTone, StyleSet.Emoji/SkinTone, StyleProps.Emoji, DefaultFor/PropsFor completed
id content status
annotation EmojiAnnotation (Center, Bounds, Render met DrawImage en schaduw, Move) completed
id content status
picker EmojiPickerButton UserControl: zoeken, categorie-tabs, gevirtualiseerd raster, preview, huidskleur, recent completed
id content status
editor EditorWindow: toolbarknop, EmojiGroup in PropsPanel, CreateAnnotation, stempel-case, sneltoets J, hint, stijl toepassen op selectie completed
id content status
settings AppSettings.RecentEmoji en controle van ToolbarPanel-volgorde voor het nieuwe item completed
id content status
verify Builden en testen: plaatsen, wisselen, huidskleur, zoeken NL/EN, export/kopiëren, undo completed
false

Emoji-gereedschap met Twemoji-kiezer

Aanpak

WPF tekent Segoe UI Emoji alleen zwart-wit. Daarom leveren we de Twemoji-set van emoji-datasource mee. Dat is dezelfde bron die emoji-mart gebruikt voor zijn "twitter"-set:

  • emoji.json: namen, categorieën, sorteervolgorde, huidskleurvarianten en de positie van elke emoji in het sheet.
  • sheet_twitter_64.png: één spritesheet waarin elke emoji 64 px groot is, met 1 px opvulling.
  • CLDR annotations/nl.json: Nederlandse namen en trefwoorden, zodat je ook in het Nederlands kunt zoeken.

Een emoji wordt een stempel-annotatie, net als StepAnnotation en CursorAnnotation. Je klikt om hem te plaatsen, en daarna kun je hem verplaatsen, ongedaan maken en exporteren via de bestaande renderpijplijn.

flowchart LR
    Assets["Assets/Emoji: json + sheet + nl"] --> Catalog[EmojiCatalog]
    Catalog --> Picker[EmojiPickerButton]
    Catalog --> Anno[EmojiAnnotation]
    Picker -->|"gekozen emoji + huidskleur"| Style[StyleSet.Emoji]
    Style --> Anno
    Anno --> Surface[AnnotationSurface en ImageExporter]

Bestanden

Assets (nieuw): src/Kniip/Assets/Emoji/ met emoji.json, twemoji-64.png en cldr-nl.json. Deze komen in src/Kniip/Kniip.csproj als <Resource Include="Assets\Emoji\*" />. De bestanden worden eenmalig gedownload met een klein script, tools/fetch-emoji.ps1, dat vaste versies van emoji-datasource-twitter (15.x) en cldr-json binnenhaalt. De bestanden zelf worden ingecheckt, zodat de build offline blijft werken.

src/Kniip/Editor/Emoji/EmojiCatalog.cs (nieuw)

  • Leest bij het eerste gebruik de json en het sheet (lazy, statisch). Emoji die niet in de Twitter-set zitten (has_img_twitter) en verouderde varianten (obsoleted_by) worden overgeslagen.
  • Het model is EmojiInfo met deze velden: Unified, Char, Name, ShortNames, Category, SortOrder, Keywords (Engels plus Nederlands) en SkinVariations (een dictionary van toon naar sheetpositie).
  • ImageSource Get(string unified, SkinTone tone): een CroppedBitmap uit het sheet, in een cache en frozen.
  • IEnumerable<EmojiInfo> Search(string query) zoekt in namen, shortcodes en trefwoorden, zonder op hoofdletters te letten.
  • Categorieën in de volgorde van emoji-mart, met Nederlandse labels: Recent, Smileys en emotie, Mensen, Dieren en natuur, Eten en drinken, Activiteiten, Reizen en plaatsen, Objecten, Symbolen, Vlaggen.

src/Kniip/Editor/Annotations/EmojiAnnotation.cs (nieuw)

  • Een stempel zoals CursorAnnotation: Center als Point, de grootte komt uit Style.Size, en Bounds is een vierkant rond Center.
  • Render gebruikt dc.DrawImage(EmojiCatalog.Get(Style.Emoji, Style.SkinTone), Bounds). Bij Style.Shadow komt er een schaduw onder, op dezelfde manier als in RenderHelpers.DrawWithShadow, maar dan voor een afbeelding (met een DrawingGroup en een DropShadowEffect-equivalent, of een offset-kopie met lage opaciteit).
  • Er gebruikt RenderOptions.SetBitmapScalingMode(HighQuality) voor nette schaling.

src/Kniip/Editor/StyleSet.cs

  • ToolKind.Emoji komt achter Cursor.
  • Nieuwe enum SkinTone { Default, Light, MediumLight, Medium, MediumDark, Dark }.
  • StyleSet krijgt string Emoji = "1f44d" (duim omhoog) en SkinTone SkinTone.
  • Nieuwe StyleProps.Emoji = 8192.
  • DefaultFor: ToolKind.Emoji => new StyleSet { Size = 48, Shadow = false }.
  • PropsFor: ToolKind.Emoji => StyleProps.Emoji | StyleProps.Size | StyleProps.Shadow.

src/Kniip/Editor/EmojiPickerButton.xaml(.cs) (nieuw)

Dit volgt hetzelfde patroon als ColorPickerButton: een ToggleButton met een Popup, en het event EmojiChanged. De popup is ongeveer 350x420 en bevat:

  • Een zoekveld bovenaan, dat focus krijgt zodra de popup opent.
  • Een rij met categorie-tabs. Een klik scrollt naar de bijbehorende sectie.
  • Een gevirtualiseerd raster: ItemsControl met VirtualizingStackPanel en per categorie een rij van negen emoji van 32 px.
  • Onderaan een preview met de naam en :shortcode: van de emoji waar je met de muis boven hangt, plus een huidskleurkiezer met zes bolletjes.
  • Na een keuze sluit de popup.

src/Kniip/Settings/AppSettings.cs

  • Nieuwe instelling List<string> RecentEmoji, met maximaal 18 items en de laatst gekozen emoji vooraan. Deze lijst vult de tab "Recent".

src/Kniip/Editor/EditorWindow.xaml

  • Een nieuwe RadioButton Tag="Emoji" achter Cursor, met ItemId="Emoji" en Title="Emoji", tooltip "Emoji plaatsen (J)" en als icoon het Segoe Fluent-glyph &#xE76E; (Emoji2).
  • In PropsPanel komt een EmojiGroup met EmojiPickerButton. SizeGroup en ShadowGroup worden hergebruikt.

src/Kniip/Editor/EditorWindow.xaml.cs

  • CreateAnnotation: ToolKind.Emoji => new EmojiAnnotation { Center = p, Style = style }.
  • De stempel-case in Surface_MouseLeftButtonDown (rond regel 490) krijgt er case ToolKind.Emoji: bij.
  • CursorForTool: Emoji gebruikt Cursors.Hand.
  • Sneltoets Key.J: SelectTool(ToolKind.Emoji).
  • Hinttekst: "Klik om de gekozen emoji te plaatsen; kies een andere emoji in de balk eronder."
  • UpdatePropsPanel en het toepassen van stijl op een geselecteerd object krijgen StyleProps.Emoji erbij. Zo kun je de emoji van een geplaatste stempel wisselen.
  • De grootte-opties voor Emoji: 24, 32, 48, 64, 96 en 128. Boven 64 wordt het bitmap opgeschaald; dat is acceptabel.

src/Kniip/Editor/ToolbarPanel.cs

  • Controleren of een opgeslagen ToolbarOrder zonder "Emoji" het nieuwe item gewoon op de standaardplek toont. Is dat niet zo, dan wordt dat ingebouwd.

Aandachtspunten

  • De app wordt ongeveer 3 tot 8 MB groter door het sheet en de json. Het sheet wordt pas geladen als je het Emoji-gereedschap voor het eerst gebruikt.
  • Twemoji valt onder CC-BY 4.0. De naamsvermelding komt in de README of het Over-scherm.
  • Bestaande stijlen in de instellingen blijven compatibel, omdat de nieuwe velden standaardwaarden hebben.