Saltar al contenido
CrossFly es 100% open sourceSíguenos en GitHub
CrossFlyCrossFly
Empezar
Todos los ejemplos
RecetasEntrada123 líneas · 1 archivos

Picking a date range

DatePicker answers "which day". This answers "between which two", which has its own rules — and its own ways of being wrong.

Qué muestra esto

A period, not a day: inclusive at both ends, locale-aware, and it refuses dates that do not exist.

Ejecutarlo en tu máquina

Cada ejemplo es una Window normal, así que el lanzador solo necesita su nombre.

gradlew lwjgl3:run --args="classname dev.cf.recipe.R07DateRange"
Editarlo

Java se compila antes de ejecutarse, así que el navegador no puede reconstruir una edición por su cuenta: el código que ves aquí se convirtió en JavaScript con TeaVM antes de publicarse. Copia el archivo a un proyecto y funciona sin cambios en las cuatro plataformas; el comando de arriba es toda la preparación.

Ejecutándose aquíCrossFly 0.1.32
Iniciando la aplicación…

Compilado a JavaScript por TeaVM: es el mismo código, no un vídeo de él. · Todos los ejemplos

Qué usa

Tipos del framework que toca este ejemplo. Los enlazados tienen página de referencia.

ButtonCardComponentDateRangePickerDebugGapLabelLocaleFormatsScreenStylesWidgets

El código

Completo, sin recortes. Es el archivo, no un fragmento.

Crudo
dev/cf/recipe/R07DateRange.java
package dev.cf.recipe;

import dev.cf.Tones;

import dev.crossfly.ui.*;
import dev.crossfly.ui.color.*;
import dev.crossfly.ui.graphics.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.picker.*;
import dev.crossfly.ui.style.*;
import dev.crossfly.util.LocaleFormats;

import static dev.crossfly.ui.Widgets.*;

/**
 * A period, not a day: inclusive at both ends, locale-aware, and it refuses dates that do not exist.
 */
public class R07DateRange extends Recipe
{
   private Label resultado;

   public String title()
   {
      return "Picking a date range";
   }

   public String note()
   {
      return "DatePicker answers \"which day\". This answers \"between which two\", which has its own"
         + " rules — and its own ways of being wrong.";
   }

   public void build(Component body) throws Exception
   {
      resultado = label("no period yet", 1.2f, true, Tones.accent(), Position.START);
      resultado.testTag("recipe.range");

      Button abrir = Tones.action("Choose a period");
      abrir.testTag("recipe.range.open");
      abrir.onAction(c -> abrir());
      body.add(LAY_AUTO, outgap(abrir, 0, 0, 0, 1f));
      body.add(LAY_AUTO, resultado);

      // The rules are public and pure: they can be tested with no window at all, which is where
      // most of the defects of a control like this really live.
      // The rules go on a surface of their own: they are the OTHER half of the recipe, not a
      // footnote to the picker above, and loose grey lines read as a footnote.
      Card regras = Tones.card(Tones.support());
      regras.getStyle()
         .outgap(Gap.ofFont(0, 1.5f, 0, 0));
      regras.add(LAY_AUTO, Tones.head(0xE6B1, "The rules, with no UI involved", Tones.support()));
      linha(regras, dia(1, 7, 2026) + " to " + dia(31, 7, 2026) + " is "
         + DateRangePicker.dayCount("2026-07-01", "2026-07-31") + " days");
      linha(regras, "a day to itself is " + DateRangePicker.dayCount("2026-07-27", "2026-07-27")
         + " day, not zero");
      linha(regras, dia(31, 2, 2026) + " parses to " + DateRangePicker.toIso(dia(31, 2, 2026)));
      linha(regras, dia(29, 2, 2024) + " parses to " + DateRangePicker.toIso(dia(29, 2, 2024)));
      body.add(LAY_AUTO, regras);
   }

   /**
    * A day, month and year written the way THIS device writes dates.
    *
    * <p>{@link DateRangePicker#toIso(String)} reads a masked date in the order the device uses, so
    * a demonstration of it cannot spell its own examples in one fixed order. These four lines were
    * written as "31/02" and "29/02/2024", which is day-first: on a month-first device the reader
    * was told that a real leap day "parses to null" — true of the string as written there, and
    * exactly the opposite of the rule the line exists to show. On a year-first device both were
    * nonsense. Same three numbers, formatted for whoever is reading, and the rules hold anywhere.</p>
    *
    * @param d day, 1-based
    * @param m month, 1-based
    * @param y full year
    * @return the date in the device's own order and separator
    */
   private static String dia(int d, int m, int y)
   {
      // The parts are arranged by hand rather than through DateTimeUtils.formatDate because that
      // one validates, and one of the dates below does not exist on purpose — printing it is the
      // whole point of the line it appears in.
      String dd = d < 10 ? "0" + d : String.valueOf(d);
      String mm = m < 10 ? "0" + m : String.valueOf(m);
      char sep = LocaleFormats.dateSeparator;
      switch (LocaleFormats.dateFormat)
      {
         case MDY:
            return mm + sep + dd + sep + y;
         case YMD:
            return String.valueOf(y) + sep + mm + sep + dd;
         default: // DMY
            return dd + sep + mm + sep + y;
      }
   }

   private void linha(Component body, String t) throws Exception
   {
      body.add(LAY_AUTO, outgap(label(t, 1f, false, Styles.captionColor, Position.START),
         0, 0, 0, .3f));
   }

   private void abrir()
   {
      try
      {
         new DateRangePicker().title("Custom period")
            .subtitle("Both ends are included.")
            .show(a ->
            {
               // null = dismissed. The dates come back in ISO, whatever order is displayed.
               DateRangePicker.Range r = (DateRangePicker.Range) a;
               resultado.setText(r == null ? "dismissed"
                  : r.from + " to " + r.to + " (" + r.days + " days)");
               resultado.setValidLayout(false);
               Screen.repaint();
            });
      }
      catch (Exception e)
      {
         dev.crossfly.util.Debug.handle(e);
      }
   }
}
Para una IA

Versiones de esta página legibles por máquina, para que un modelo lea el estante en vez de adivinar la API.

Este ejemplo, en JSONEste ejemplo, en Markdown
AnteriorChoosing from a listSiguienteReordering a list