Implementar Modo Oscuro en tus apps macOS

Desde Xojo 2018r3 ya es posible implementar el Modo Oscuro (Dark Mode) en tus aplicaciones macOS. Se trata de la capacidad introducida por Apple en el sistema operativo desde la versión 10.14 (Mojave) y que, a buen seguro, los usuarios esperan ver implementado también en tus productos, de modo que el aspecto de la interfaz gráfica de tus aplicaciones se adapte entre los modos Claro y Oscuro a medida que el usuario conmute dichas opciones a través del panel General de las Preferencias del Sistema.

La buena noticia es que si tus aplicaciones Xojo se limitan a utilizar los controles de UI incluidos por omisión en la Librería, entonces todo lo que tendrás que hacer para implementar el soporte será abrir el proyecto en cuestión en el IDE de Xojo y volver a compilarla; dado que por omisión ya se encuentra activado el soporte de Modo Oscuro entre las opciones disponibles en el Panel Inspector para la sección Shared de ajustes de compilación en el navegador de proyectos.

Cuando las aplicaciones se ejecuten sobre Mojave estas se comportarán tal y como esperaríamos, reaccionando de inmediato a los ajustes realizados por el usuario; mientras que si las ejecutamos en anteriores versiones del sistemas operativo, entonces todos los elementos de interfaz de usuario se mostrarán tal y como venía siendo habitual empleando el modo claro.

Sin embargo, lo más probable es que tus proyectos también incluyan componentes personalizados de interfaz gráfica basados en Canvas; y es precisamente en estos casos en los que se hace preciso modificar el evento Paint de dichos controles para que tengan la capacidad de dibujarse con un esquema de color u otro en función de cuál sea el modo de visualización seleccionado por el usuario en cada momento. Para ello, además, desde Xojo 2018r4 contamos con un evento específico del objeto App denominado AppearanceChanged y que es invocado cada vez que la aplicación detecte un cambio de modo.

Es decir, por un lado tenemos nuestros objectos (instancias de nuestros componentes UI personalizados basados en Canvas) que necesitan reaccionar al cambio de modo; y por otro tenemos el evento AppearanceChanged que nos sirve como punto de entrada para que nuestra aplicación advierta el cambio entre modos y pueda reaccionar a ellos. ¿Cómo unimos ambos elementos? Una de las técnicas que puedes utilizar, y que es la que te propongo en este artículo, es la basada precisamente en el patrón de diseño Observer, donde cada uno de los objetos interesados en ser notificados con cada cambio de modo se suscriben a un emisor.

Así, cada vez que se dispare el evento AppearanceChanged su código simplemente tendrá que recorrer la estructura de datos que utilicemos para el emisor (por ejemplo un simple Array) e invocar en cada uno de los miembros el método responsable de actualizar el dibujado de los componentes; por ejemplo un simple Invalidate.

Con lo anterior ya habremos resuelto dos de los tres aspectos que hemos de tener en cuenta para que nuestros componentes UI utilicen un esquema de color adecuado en cada uno de los modos; porque, ¿cómo podemos saber dentro del evento Paint de nuestras clases basdas en Canvas si estamos en modo Oscuro o modo Claro? La respuesta, también introducida en la release Xojo 2018r3 se encuentra en el método global IsDarkMode que nos devolverá un booleano con valor True si, efectivamente, nuestra aplicación se está ejecutando en Modo Oscuro, mientras que el valor False indicará lo contrario.

Por tanto, el código del evento Paint simplemente tendrá que hacer los ajustes de esquema de color necesarios en base al valor devuelto por dicho método. Así de simple.

Para ver todo esto en funcionamiento, he crearo un ejemplo realmente simple que puedes descargar desde este enlace y en el que se cambia al vuelo el color de relleno en cada uno de los bloques dibujados en función de que se esté utilizando el Modo Claro o Modo Oscuro sobre Mojave.

Related Posts / Entradas Relacionadas

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *