Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/writing-sugar-activities.tex
blob: 59a214c6c8f9b0a63e52ae81b7c314afb9ddf90e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
\mode* % Reset \mode<all> from slides.tex

\section{\en{Overview of Sugar and GTK+}\es{Visión general de Sugar y GTK+}}

\en{The Sugar platform is what runs on the XO. Sugar itself is written in
Python, but uses a system called GTK+ as its underlying UI toolkit. GTK+ is a
popular UI toolkit, used by many projects on Linux (not just on the XO).}
\es{La plataforma de Sugar es lo que se ejecuta en la XO. Sugar sí está escrito
en Python, pero utiliza un sistema llamado GTK+ como su kit de herramientas de
interfaz de usuario (IU) subyacente. GTK+ es un popular juego de herramientas de
interfaz de usuario, que se utiliza por muchos proyectos en Linux (y no sólo en
la XO).}

\en{Sugar's distinctive appearance is due to a theme it applies to the default
GTK+ widgets. Without this theme, activities on the XO would look very similar
to normal Linux programs (such as gedit).}
\es{El aspecto distintivo de Sugar es debido a un tema que se aplica a los
widgets GTK+ predeterminados. Sin este tema, las actividades en la XO se vería
muy similar a los programas normales de Linux (como gedit).}

\en{As with Python, there are two major versions of GTK+ available at the
moment: GTK+~2 and GTK+~3. GTK+~3 is the recommended version, and is available
on the XO. All software should be written using GTK+~3 using GIR (GObject
Introspection) and \emph{not} PyGTK (which is out of date).}
\es{Al igual que con Python, hay dos versiones principales de GTK+ disponibles
en este momento: GTK+~2 y GTK+~3. GTK+~3 es la versión recomendada, y está
disponible en la XO. Todo el software debe ser escrito usando GTK+~3 y GIR
(introspección GObject) y \emph{no} PyGTK (que es obsoleta).}

\en{Similarly, there are two versions of Sugar code available: \texttt{sugar}
and \texttt{sugar3}. \texttt{sugar} uses GTK+~2, whereas \texttt{sugar3} uses
GTK+~3. All new software should be written using \texttt{sugar3}.}
\es{Del mismo modo, hay dos versiones de código de Sugar disponibles:
\texttt{sugar} y \texttt{sugar3}. \texttt{sugar} usa GTK+~2, mientras que
\texttt{sugar3} usa GTK+~3. Todas las novedades software debe ser escrito con
\texttt{sugar3}.}

\begin{frame}{\en{Sugar and GTK+}\es{Sugar y GTK+}}
\begin{itemize}
    \item{\en{All XO activities use Sugar}
          \es{Todas las actividades XO utilizan Sugar}}
    \item{\en{Sugar is built on GTK+~3}\es{El Sugar se basa en GTK+~3}}
    \item{\en{Use \texttt{sugar3} and GTK+~3}
          \es{Debe utilizar \texttt{sugar3} y GTK+~3}}
\end{itemize}
\end{frame}


\section{\en{Introduction to GTK+}\es{Introducción a GTK+}}

\en{GTK+ is based on the concept of a hierarchy of \emph{widgets}. A widget is
a single graphical control, such as a button, some text, a toolbar, or a
window. These widgets are built into a hierarchy, with child widgets inside
parent widgets. For example, when a button is shown next to an image, a menu bar
and a label in a window, this widget hierarchy is used:}
\es{GTK+ se basa en el concepto de una jerarquía de \emph{widgets}. Un widget es
un control gráfico único, tal como un botón, un texto, una barra de
herramientas, o una ventana. Estos widgets están integradas en una jerarquía,
con widgets hijos dentro de los widgets de los padres. Por ejemplo, cuando se
muestra un botón al lado de la imagen, una barra de menús y una etiqueta en una
ventana, se utiliza esta jerarquía de controles:}

\begin{frame}{\en{GTK+ widget hierarchy}\es{Jerarquía de widgets de GTK+}}
\begin{itemize}
    \item{\texttt{Gtk.Window}\begin{itemize}
        \item{\texttt{Gtk.Box}\begin{itemize}
            \item{\texttt{Gtk.MenuBar}}
            \item{\texttt{Gtk.Label}}
            \item{\texttt{Gtk.Image}}
            \item{\texttt{Gtk.Button}}
        \end{itemize}}
    \end{itemize}}
\end{itemize}
\end{frame}

\begin{frame}{\en{GTK+ widget hierarchy}\es{Jerarquía de widgets de GTK+}}
\begin{figure}[h!]
    \centering
    \includegraphics[width=0.4\textwidth]{example-ui.png}
    \caption{\en{The example UI.}
             \es{Un ejemplo de un IU.}}
    \label{fig:example-ui}
\end{figure}
\end{frame}

\en{Widgets are roughly divided between normal controls and layout containers
(such as \texttt{Gtk.Box} in the example hierarchy). Other code in GTK+ supports
key bindings, drag-and-drop and the clipboard.}
\es{Widgets están divididos más o menos entre los controles normales y
contenedores de diseño (como \texttt{Gtk.Box} en la jerarquía de ejemplo). Otro
código en GTK+ soporta atajos de teclado, arrastrar y soltar y el portapapeles.}

\note{Give an interactive demo of Glade and \texttt{example-ui.ui} now.}

\en{\emph{Glade} is a popular tool for building UIs with GTK+. It isn't
normally used when creating Sugar activities, but is useful for exploring the
widget hierarchy.}
\es{\emph{Glade} es una herramienta popular para la creación de IUs con GTK+. No
se suele utilizar cuando se crean actividades para Sugar, pero es útil para
explorar la jerarquía de widgets.}


\section{\en{Building an interactive UI}\es{Construcción de una IU interactiva}}

\en{To build a UI in GTK+, construct a Python object for each widget, and then
call methods on the container widgets to add child widgets to parents and thus
construct a hierarchy.}
\es{Para construir una IU en GTK+, construir un objeto de Python para cada
widget, y luego llamar a métodos en los widgets de contenedores para añadir
hijos a los padres y así la construcción de una jerarquía.}

\begin{frame}[fragile]
\frametitle{\en{Constructing a GTK+ widget hierarchy}
            \es{Construcción de una jerarquía de widgets de GTK+}}
\begin{lstlisting}[language=Python,basicstyle={\ttfamily\footnotesize}]
from gi.repository import Gtk

window = Gtk.Window(title='Hola Mundo')

# Crear widget contenedor.
box = Gtk.Box()
box.set_orientation(Gtk.Orientation.VERTICAL)
window.add(box)
# Crear una etiqueta, una imagen y un boton.
label = Gtk.Label('Logo OLPC:')
box.add(label)
image = Gtk.Image()
image.set_from_file('olpc-square_logo.jpg')
box.add(image)
button = Gtk.Button()
button.set_label('Boton')
box.add(button)

# Mostrar la IU.
window.show_all()
Gtk.main()
\end{lstlisting}
\end{frame}


\en{In this example, the last two lines of code require explanation. Every GTK+
widget can be hidden, and all are hidden by default. Before they can be used by
the user they need to be shown --- either by calling the \texttt{show()} method
on each widget, or by calling the \texttt{show\_all()} method on one of the
container widgets which contains them (such as the top-level window, for
example).}
\es{En este ejemplo, las dos últimas líneas de código requieren de una
explicación. Cada widget de GTK+ se puede ocultar, y todos se oculta de manera
predeterminada. Antes de que puedan ser utilizados por el usuario, es necesario
que se muestra --- o bien llamando al método \texttt{show()} de cada widget, o
llamando al método \texttt{show\_all()} en uno de los widgets de contenedor que
los contiene (como la ventana de nivel superior, por ejemplo).}

\en{The last line of code starts the GTK+ \emph{main loop}. This is what
handles user input and drawing of widgets in a UI. The main loop is an infinite
loop which:}
\es{La última línea de código se inicia el \emph{bucle principal} de GTK+. Esto
es lo que se encarga de la entrada del usuario y el dibujo de widgets en una IU.
El bucle principal es un bucle infinito que:}

\begin{frame}{\en{GTK+ main loop}\es{Bucle principal de GTK+}}
\begin{enumerate}
    \item{\en{Receives input events from the user (such as mouse movements or
              keyboard button presses)}
          \es{Recibe los eventos de entrada del usuario (por ejemplo, los
              movimientos del ratón o pulsaciones de botones del teclado)}}
    \item{\en{Calls \emph{event handlers} for those events}
          \es{Llamadas \emph{controladores de eventos} para los eventos}}
    \item{\en{Waits for the next input event, then loops}
          \es{Espera a que el próximo evento de entrada, entonces se realiza un
              bucle}}
\end{enumerate}
\end{frame}
% TODO: Diagram of the main loop?

\en{This is a standard event-based programming model. It means that after
calling the \texttt{Gtk.main()} function, all code in your program is executed
inside callbacks from this main loop. A callback is where the main loop calls
a function provided by your code: the main loop \emph{calls back} to your
code.}
\es{Este es un modelo de programación estándar basado en eventos. Esto significa
que después de llamar a la función \texttt{Gtk.main()}, todo el código de su
programa se ejecuta dentro de callbacks de este bucle principal. Un callback es
donde el bucle principal llama a una función proporcionada por su código: el
bucle principal \emph{vuelve a llamar} a su código.}


\section{\en{Signal handling}\es{Manejo de señales}}

\en{Almost all callbacks in GTK+ are for \emph{signals} from widgets. These
correspond to events on the widgets. For example, the \texttt{Button} widget
emits a \texttt{clicked} signal when the user clicks it. Zero or more callbacks
can be \emph{connected} for this signal, all of which will be called from the
main loop when the button is clicked.}
\es{Casi todas las callbacks en GTK+ son para señales de widgets. Estos
corresponden a eventos en los widgets. Por ejemplo, el widget \texttt{Button}
emite una señal de \texttt{clicked} cuando el usuario hace clic en él. Cero o
más callbacks se pueden conectar a esta señal, todos los cuales serán llamados
desde el bucle principal cuando se hace clic en el botón.}

\en{A signal handler can be connected by calling the \texttt{connect()} method,
passing the name of the signal, and the name of the function to use as a
callback. This function must accept the parameters specified in the
documentation for the signal. It is common practice (though not required) to
suffix callback function names with \texttt{\_cb} (which stands for
`callback').}
\es{Un manejador de la señal se puede conectar mediante una llamada al método
\texttt{connect()}, pasando el nombre de la señal, y el nombre de la función
para utilizarla como un callback. Esta función debe aceptar los parámetros
especificados en la documentación de la señal. Es una práctica común (aunque no
es obligatorio) a los nombres de funciones callback con sufijo \texttt{\_cb}
(que significa `callback').}

\en{In this example, we subclass \texttt{Gtk.Window} so that the signal callback
can be included as a private method of the window. This is a tidy way to do
things, as it prevents callbacks from different windows getting mixed up.}
\es{En este ejemplo, subclase \texttt{Gtk.Window} de modo que el callback de la
señal puede ser incluido como un método privado de la ventana. Esta es una
manera ordenada de hacer las cosas, ya que evita que callbacks de diferentes
ventanas se mezclen.}

\begin{frame}[fragile]
\frametitle{\en{GTK+ signal handlers}\es{Manejadores de señales de GTK+}}
\begin{lstlisting}[language=Python,basicstyle={\ttfamily\footnotesize}]
# Subclase Window para crear una ventana.
class MyWindow(Gtk.Window):
    def __init__(self):
        super(MyWindow, self).__init__()

        # Crear y anadir un boton.
        button = Gtk.Button('Hola Mundo')
        button.show()
        self.add(button)

        # Conecte un manejador de senales.
        button.connect('clicked',
            self.__button_clicked_cb)

    def __button_clicked_cb(self, button):
        print('Boton se hizo clic!')

window = MyWindow()
window.show()
Gtk.main()
\end{lstlisting}
\end{frame}

\en{Signal handling is one of the key features of GTK+, and is worth
understanding.}
\es{Manipulación de las señales es una de las características principales de
GTK+, y vale la pena comprensión.}

\begin{frame}{\en{Signal handling tutorials}\es{Tutoriales sobre el manejo de señales}}
\begin{itemize}
    \item{\url{\en{https://developer.gnome.org/gnome-devel-demos/stable/signals-callbacks.py.html.en}
               \es{https://developer.gnome.org/gnome-devel-demos/stable/signals-callbacks.py.html.es}}}
    \item{\url{http://python-gtk-3-tutorial.readthedocs.org/en/latest/basics.html\#main-loop-and-signals}}
\end{itemize}
\end{frame}


\section{\en{GTK+ documentation}\es{Documentación de GTK+}}

\en{GTK+ is a huge library, and covering it in detail here would take too long.
There are several good tutorials for using GTK+ in Python, available in several
languages. It is recommended that you read them and practice the exercises they
give. The \href{https://developer.gnome.org/gtk3/stable/ch03.html}{GTK+ widget
gallery} contains screenshots of every GTK+ widget, and links to their API
documentation.}
\es{GTK+ es una gran librería, y cubriendo en detalle aquí tomaría demasiado
tiempo. Hay varios buenos tutoriales para el uso de GTK+ en Python, disponible
en varios idiomas. Se recomienda que los lea y aplique los ejercicios que dan.
La \href{https://developer.gnome.org/gtk3/stable/ch03.html}{galería de widgets
de GTK+} contiene imágenes de todos los widgets de GTK+, y enlaces a la
documentación de la API.}

\begin{frame}{\en{GTK+ tutorials}\es{Tutoriales de GTK+}}
\begin{itemize}
    \item{\en{\url{https://developer.gnome.org/gnome-devel-demos/stable/tutorial.py.html.en}}
          \es{\url{https://developer.gnome.org/gnome-devel-demos/stable/tutorial.py.html.es}}}
    \item{\en{\url{https://developer.gnome.org/gnome-devel-demos/stable/beginner.py.html.en}}
          \es{\url{https://developer.gnome.org/gnome-devel-demos/stable/beginner.py.html.es}}}
    \item{\url{http://python-gtk-3-tutorial.readthedocs.org/en/latest/index.html}}
    \item{\url{https://developer.gnome.org/gtk3/stable/ch03.html}}
\end{itemize}
\end{frame}

\en{The GTK+ API documentation is currently only available for the C
programming language. However, converting function names between C and Python
is fairly simple, so you can use the C API documentation for Python.}
\es{La documentación del API de GTK+ sólo está disponible para el lenguaje de
programación C. Sin embargo, la conversión de nombres de funciones entre C y
Python es bastante simple, por lo que puede utilizar la documentación de la API
C con Python.}

\en{To convert a C function name to a Python method name, remove underscores,
change it to camelcase, and separate `gtk', the class name, and the method
name. Python constructors become \texttt{*\_new()} functions in C. Constant
values are entirely capitalised in C, and only partially capitalised in
Python.}
\es{Para convertir un nombre de función C para un nombre de método Python,
retire subrayado, cambiar a CamelCase, y separado `gtk' del nombre de la clase y
del nombre del método. Constructores Python vuelven funciones \texttt{*\_new()}
en C. Valores constantes están completamente activados en C, y sólo parcialmente
capitalizado en Python.}

\begin{frame}{\en{GTK+ API documentation}\es{Documentación de la API de GTK+}}
\begin{block}{}
\url{https://developer.gnome.org/gtk3/stable/gtkobjects.html}
\end{block}
\begin{block}{\en{Conversion}\es{Conversión}}
{\small\begin{align*}
    \mathbf{Python} &\leftrightarrow \mathbf{C} \\
    \mathtt{Gtk.Window.set\_title()} &\leftrightarrow
        \mathtt{gtk\_window\_set\_title()} \\
    \mathtt{Gtk.Button()} &\leftrightarrow \mathtt{gtk\_button\_new()} \\
    \mathtt{Gtk.ToggleButton.get\_active()} &\leftrightarrow
        \mathtt{gtk\_toggle\_button\_get\_active()} \\
    \mathtt{Gtk.Orientation.VERTICAL} &\leftrightarrow
        \mathtt{GTK\_ORIENTATION\_VERTICAL}
\end{align*}}
\end{block}
\end{frame}


\section{\en{Writing an activity}\es{Escribir una actividad}}

\en{Fundamentally, a Sugar activity is a GTK+ application which provides a
single GTK+ \texttt{Window} widget for the activity to use. This window forms
the root of the activity's widget hierarchy, just as in a normal GTK+
application. Events and callbacks are handled similarly.}
\es{Fundamentalmente, una actividad de Sugar es una aplicación de GTK+ que
proporciona un solo widget \texttt{Window} de GTK+ para la actividad de usar.
Esta ventana se forma la raíz de la jerarquía de widgets de la actividad, al
igual que en una aplicación normal de GTK+. Eventos y callbacks se manejan de
manera similar.}

\en{To create an activity, subclass the
\texttt{sugar3.activity.activity.Activity} class
in Python. This \texttt{Activity} class provides a method to parent your
activity's widget tree: \texttt{set\_canvas()}. By creating a widget hierarchy
and passing it to this function, the interface for an activity can be created.}
\es{Para crear una actividad, debe subclase de la clase
\texttt{sugar3.activity.activity.Activity} en Python. Esta clase
\texttt{Activity} proporciona un método para adjuntar la jerarquía de widgets de
su actividad: \texttt{set\_canvas()}. Mediante la creación de una jerarquía de
widgets y pasarlo a esta función, se puede crear la interfaz para una
actividad.}

\begin{frame}[fragile]
\frametitle{\en{Creating an activity UI}\es{Creación de una IU de la actividad}}
\begin{lstlisting}[language=Python,basicstyle={\ttfamily\small}]
from sugar3.activity import activity

class HolaMundoActivity(activity.Activity):
    def __init__(self, handle):
        super(HolaMundoActivity, self).__init__(handle)

        box = Gtk.Box()
        label = Gtk.Label('Hola Mundo!')
        button = Gtk.Button('Boton')

        label.show()
        box.add(label)

        button.show()
        box.add(button)

        box.show()
        self.set_canvas(box)
\end{lstlisting}
\end{frame}

\en{When subclassing \texttt{sugar3.activity.activity.Activity}, three methods
must be implemented. \texttt{\_\_init()\_\_} is the normal object constructor,
and is called when your activity is started by the user. The \texttt{handle}
parameter provides the activity ID and access to sharing services (which aren't
covered here).}
\es{Al crear subclases de \texttt{sugar3.activity.activity.Activity}, tres
métodos se deben implementar. \texttt{\_\_init\_\_()} es el constructor de
objeto normal, y se llama cuando su actividad se inicia por el usuario. El
parámetro \texttt{handle} proporciona el ID de la actividad y el acceso a
servicios para compartir (que no se cubre en este manual).}

\en{\texttt{read\_file} is called after \texttt{\_\_init\_\_} when resuming an
activity from the Journal. The \texttt{file\_path} parameter is the path of a
file containing the saved Journal data. Similarly, \texttt{write\_file} is
called when the user wants to save the activity to the Journal (either
explicitly, when closing the activity, or when switching to another activity),
and the \texttt{file\_path} is the path of a file which the Journal entry
should be saved to.}
\es{\texttt{read\_file} es llamada después \texttt{\_\_init\_\_} cuando se
reanuda la actividad en el Diario. El parámetro \texttt{file\_path} es la ruta
de un archivo que contiene los datos de diario guardados. Del mismo modo,
\texttt{write\_file} se llama cuando el usuario desea guardar la actividad con
el Diario (ya sea de manera explícita, al cerrar la actividad, o cuando se
cambia a otra actividad), y el \texttt{file\_path} es la ruta de un archivo que
la entrada de Diario debe ser guardado en.}

\begin{frame}{\en{Required activity methods}
              \es{Métodos necesarios para actividades}}
\begin{itemize}
    \item{\texttt{\_\_init\_\_(self, handle)}}
    \item{\texttt{read\_file(self, file\_path)}}
    \item{\texttt{write\_file(self, file\_path)}}
\end{itemize}
\end{frame}

\en{The \texttt{Activity} class provides several other methods (apart from
\texttt{set\_canvas()}) which can be called from within the activity code to
perform various tasks such as forcing the activity to be saved to the Journal,
closing the activity, and starting to share the activity on the network. Look
at the
\href{https://github.com/sugarlabs/sugar-toolkit-gtk3/blob/master/src/sugar3/activity/activity.py}{source code} for \texttt{sugar3.activity.activity.Activity} for
details.}
\es{La clase \texttt{Activity} ofrece varios métodos (además de
\texttt{set\_canvas()}), que se puede llamar desde dentro del código de
actividad para realizar diversas tareas, tales como obligar a la actividad que
se guardan en el Diario, el cierre de la actividad, y empezar a compartir la
actividad en la red. Mira
\href{https://github.com/sugarlabs/sugar-toolkit-gtk3/blob/master/src/sugar3/activity/activity.py}{el código} de
\texttt{sugar3.activity.activity.Activity} para más detalles.}

\en{The most important thing to do in the \texttt{\_\_init\_\_} method is to
add a toolbar to the activity. Amongst other things, this adds a close button
to the activity.}
\es{La cosa más importante que hacer en el método \texttt{\_\_init\_\_} es
agregar una barra de herramientas a la actividad. Entre otras cosas, esto se
agrega un botón de cierre de la actividad.}

\begin{frame}[fragile]
\frametitle{\en{Adding a toolbar}\es{Adición de una barra de herramientas}}
\begin{lstlisting}[language=Python]
def __init__(self, handle):
    # Cree la caja de herramientas de
    # actividad estandar.
    toolbar_box = ToolbarBox()
    self.set_toolbar_box(toolbar_box)
    toolbar_box.show()

    main_toolbar = toolbar_box.toolbar

    activity_button = widgets.ActivityToolbarButton(self)
    main_toolbar.insert(activity_button, 0)
    activity_button.show()
\end{lstlisting}
\end{frame}


\section{\en{Packaging an activity}\es{Empaquetar una actividad}}

\en{All the files for an activity are bundled together in a special format to
form a single \texttt{.xo} file which can be executed by the XO. An \texttt{.xo}
file is just a renamed Zip archive, but it must contain three key files:
\texttt{setup.py}, \texttt{activity/activity.info} and
\texttt{activity/activity.svg}.}
\es{Todos los archivos de una actividad se agrupan en un formato especial para
formar un único archivo \texttt{.xo} que puede ser ejecutado por el XO. Un
archivo \texttt{.xo} es sólo un archivo Zip cambiado de nombre, pero debe
contener tres archivos principales: \texttt{setup.py},
\texttt{activity/activity.info} y \texttt{activity/activity.svg}.}

\es{Los nombres de archivo en Inglés no se deben traducir al Español, como el
código de Sugar espera encontrar los nombres de los archivos exactos.}

\begin{frame}{\en{XO bundle format}\es{Formato de los paquetes de XO}}
\begin{itemize}\item{\texttt{\en{ActivityName.activity}\es{NombreDeActividad.activity}}\begin{itemize}
    \item{\texttt{\en{activityname.py}\es{nombredeactividad.py}}}
    \item{\texttt{setup.py}}
    \item{\texttt{activity/}\begin{itemize}
        \item{\texttt{activity.info}}
        \item{\texttt{activity.svg}}
    \end{itemize}}
    \item{\texttt{icons/}\begin{itemize}
        \item{\en{any-custom-icons.svg}\es{los-iconos-personalizados.svg}}
        \item{$\cdots$}
    \end{itemize}}
    \item{\texttt{po/}\begin{itemize}
        \item{\texttt{de.po}}
        \item{\texttt{es.po}}
        \item{\texttt{it.po}}
        \item{$\cdots$}
        \item{\texttt{\en{ActivityName.pot}\es{NombreDeActividad.pot}}}
    \end{itemize}}
\end{itemize}}\end{itemize}
\end{frame}

\en{\texttt{activity.info} contains metadata about the activity, such as its
name, description, ID, version and software licence. \texttt{activity.svg} is
the icon for the activity. \texttt{setup.py} is used during development to build
and test the activity, and is the same for all activities.
\texttt{activityname.py} contains the code for the activity, and can have any
name --- the actual filename is referenced in \texttt{activity.info}.}
\es{\texttt{activity.info} contiene metadatos acerca de la actividad, tales como
su nombre, descripción, ID, la versión y licencia de software.
\texttt{activity.svg} es el icono de la actividad. \texttt{setup.py} se utiliza
durante el desarrollo para construir y probar la actividad, y es el mismo para
todas las actividades. \texttt{nombredeactividad.py} contiene el código para la
actividad, y puede tener cualquier nombre --- el nombre de archivo real se hace
referencia en la \texttt{activity.info}.}

% TODO: Add a lstdefinelanguage for this if I get time.
\begin{frame}[fragile]
\frametitle{\texttt{activity.info}}
\begin{lstlisting}
[Activity]
name = Pascal Triangle
summary = Addition game using Pascal's triangle.
activity_version = 1
host_version = 1
bundle_id = hn.educatrachos.pascaltriangle
icon = activity
exec = sugar-activity pascaltriangle.PascalTriangleActivity
license = GPLv2+
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{\texttt{setup.py}}
\begin{lstlisting}[language=Python]
#!/usr/bin/env python
from sugar.activity import bundlebuilder
if __name__ == "__main__":
    bundlebuilder.start()
\end{lstlisting}
\end{frame}

\en{The \texttt{icons} directory is optional, and contains any custom icons
which your activity uses (for example, in toolbars). The XO ships a few standard
icons, but not many, so activities have to provide their own in many cases.}
\es{El directorio \texttt{icons} es opcional, y contiene los iconos
personalizados que utiliza su actividad (por ejemplo, en las barras de
herramientas). La XO proporciona unos iconos estándar, pero no muchos, por lo
que las actividades tienen que proporcionar su propia en muchos casos.}

\en{The \texttt{po} directory is also optional (though highly recommended) and
contains translations of all the UI strings in the activity, so it can be run
in other languages. By convention, all UI strings in Python are written in
English --- so when writing an activity, you need to provide a Spanish
translation as \texttt{es.po}. \texttt{ActivityName.pot} is a template for the
\texttt{.po} files. Internationalisation will be covered in more detail later.}
\es{El directorio \texttt{po} también es opcional (aunque muy recomendable) y
contiene las traducciones de todas las cadenas de la IU en la actividad, por lo
que se puede ejecutar en otros idiomas. Por convención, todas las cadenas de la
IU en Python están escritos en Inglés --- así cuando se escribe una actividad,
es necesario proporcionar una traducción al Español como \texttt{es.po}.
\texttt{NombreDeActividad.pot} es una plantilla para los archivos \texttt{.po}.
Internacionalización se explica con más detalle más adelante.}


\section{\en{Version control}\es{Control de versiones}}

\en{Creating a new activity starts with creating the directory structure for it,
then by setting up version control. Version control is a way of cataloguing the
history of development of some code by storing multiple \emph{revisions} of each
file. This allows examination of the changes between each revision (as the
software is developed), and also allows the code to be reverted to a previous
revision if problems are found in later code. Importantly, version control
systems make it easy to distribute code across the Internet, by \emph{pushing}
it to remote repositories.}
\es{Crear una nueva actividad se inicia con la creación de la estructura de
directorios para que, a continuación, mediante el establecimiento de control de
versiones. El control de versiones es una manera de catalogar la historia del
desarrollo de un código mediante el almacenamiento de múltiples
\emph{revisiones} de cada archivo. Esto permite que el examen de los cambios
entre cada revisión (como se desarrolla el software), y también permite que el
código para revertir a una revisión anterior si los problemas se encuentran en
el código más adelante. Es importante destacar que los sistemas de control de
versiones facilitan la distribución del código a través de Internet,
\emph{empujándolo} a los repositorios remotos.}

\en{The recommended version control system for use with Sugar activities is
`git', a popular system used by many open source projects. There isn't
time to give a full introduction to git here, so only a few commands
will be demonstrated.}
\es{El sistema de control de versiones se recomienda su uso en las actividades
de Sugar es `git', un sistema popular y utilizado por muchos proyectos de
software libre. No hay tiempo para dar una introducción completa a git aquí, así
que sólo unos pocos comandos se demostrarán.}

\en{Executed from a terminal, in the activity's directory, \texttt{git~init}
creates a new git repository. (This only needs to be perfomed once.)
\texttt{git~add} adds files to git's list of staged files, which can be seen by
running \texttt{git~status}. \texttt{git~commit} creates a new revision in the
repository, with the changes which were staged using \texttt{git~add}. The whole
repository can then be pushed to a server. \texttt{git~log} shows the existing
revisions in the repository.}
\es{Ejecutado desde un terminal, en el directorio de la actividad,
\texttt{git~init} crea un nuevo repositorio de git. (Necesario sólo una vez.)
\texttt{git~add} agrega archivos a la lista de archivos de git organizaron, que
se puede ver mediante la ejecución de \texttt{git~status}. \texttt{git~commit}
crea una nueva revisión en el repositorio, con los cambios que se organizaron
con \texttt{git~add}. Todo el repositorio puede entonces ser empujada a un
servidor. \texttt{git~log} muestra las revisiones existentes en el repositorio.}

\begin{frame}{\en{Introduction to git}\es{Introducción a git}}
\begin{itemize}
    \item{\texttt{git~init}}
    \item{\texttt{git~add \en{file1.py file2.py}\es{archivo1.py archivo2.py} \dots}}
    \item{\texttt{git~status}}
    \item{\texttt{git~commit}}
    \item{\texttt{git~log}}
\end{itemize}
\end{frame}

\begin{frame}{\en{git resources}\es{Recursos para git}}
\begin{block}{\en{Introductions}\es{Introducciones}}
\begin{itemize}
    \item{\url{http://try.github.io/}}
    \item{\url{http://gitimmersion.com/}}
\end{itemize}
\end{block}
\begin{block}{\en{References}\es{Referencias}}
\begin{itemize}
    \item{\url{http://git-scm.com/book\es{/es}}}
    \item{\url{http://gitref.org/}}
\end{itemize}
\end{block}
\end{frame}


\en{Building the XO bundle is achieved using \texttt{setup.py}. When developing
locally, run \texttt{./setup.py~dev} from a terminal in the activity's directory
to set up the activity to run on your computer with \texttt{sugar-emulator}
(discussed later). To build the \texttt{.xo} file for distribution, run
\texttt{./setup.py~dist\_xo}. When building the \texttt{.xo} file, the script
will ignore files which aren't committed to git, so ensure all relevant files
(but not files which have been automatically generated) have been added to git
using \texttt{git~add}.}
\es{Construyendo el paquete XO se consigue utilizando \texttt{setup.py}. En el
desarrollo a nivel local, ejecute \texttt{./setup.py~dev} desde un terminal en
el directorio de la actividad para establecer la actividad se ejecute en su
equipo con \texttt{sugar-emulator} (explicado más adelante). Para generar el
archivo \texttt{.xo} para la distribución, ejecute \texttt{./setup.py~dist\_xo}.
Cuando se construye el fichero \texttt{.xo}, el script pasará por alto los
archivos que no se han añadido a git, para asegurar que todos los archivos
relevantes (pero no los archivos que se han generado de forma automática), se
han añadido git utilizando \texttt{git~add}.}

\begin{frame}{\texttt{setup.py}}
\begin{itemize}
    \item{\texttt{./setup.py~dev}}
    \item{\texttt{./setup.py~dist\_xo}}
\end{itemize}
\end{frame}


\section{\en{Emulating Sugar for testing}\es{Emulando Sugar para probar}}

\en{A recommended way to develop activities is to use \texttt{sugar-emulator},
a program which can be installed on most desktop Linux distributions. It allows
the Sugar environment to be emulated on a desktop, meaning a new activity can
be tested without being copied over to a physical XO.}
\es{Una forma recomendada para el desarrollo de actividades es utilizar
\texttt{sugar-emulator}, un programa que se puede instalar en la mayoría de las
distribuciones de Linux. Permite el entorno azúcar a emular en un escritorio, lo
que significa una nueva actividad puede ser probado sin copiarse a un XO
físico.}

\en{To run \texttt{sugar-emulator}, simply type its name into the terminal. For
extra debugging output, also set the \texttt{SUGAR\_LOG\_LEVEL} environment
variable. To run the emulator in a different language, set the \texttt{LANG}
environment variable.}
\es{Para ejecutar \texttt{sugar-emulator}, simplemente escriba su nombre en el
terminal. Para la salida de depuración extra, también establezca la variable de
entorno \texttt{SUGAR\_LOG\_LEVEL}. Para ejecutar el emulador en un idioma
diferente, establezca la variable de entorno \texttt{LANG}.}

\begin{frame}{\texttt{sugar-emulator}}
\begin{itemize}
    \item{\texttt{sugar-emulator}}
    \item{\texttt{SUGAR\_LOG\_LEVEL=debug LANG=es sugar-emulator}}
\end{itemize}
\end{frame}

\note{Give an interactive demo of \texttt{sugar-emulator} at this point.}


\en{Debugging an activity is similar to debugging any other Python program: the
simplest way is to use the \texttt{print()} function to print out values from
the program, and manually check whether they're what's expected --- or whether
those points in the program are reached at all.}
\es{Depuración de la actividad es similar a depurar cualquier otro programa de
Python: la forma más sencilla es utilizar la función \texttt{print()} para
imprimir los valores del programa, y comprobar manualmente si son lo que se
espera --- o si esos puntos en el programa se alcanzan en absoluto.}

\en{When using \texttt{sugar-emulator}, text outputted using \texttt{print()}
won't appear in the normal terminal. Instead, it is saved to a log file in
\texttt{\textasciitilde/.sugar/default/logs} which is specific to the activity.
A new log file is created every time the activity is run in a single
\texttt{sugar-emulator} session, so the number $N$ changes.}
\es{Al usar \texttt{sugar-emulator}, texto emite utilizando \texttt{print()} no
aparecerá en el terminal normal. En su lugar, se guarda en un archivo de
registro en \texttt{\textasciitilde/.sugar/default/logs}, que es específica de
la actividad. Un nuevo archivo de registro se crea cada vez que la actividad se
ejecuta en una sola sesión de \texttt{sugar-emulator}, por lo que los cambios en
el número $N$.}

\en{For a more flexible logging solution which doesn't have to be removed before
publishing the activity, use the
\href{http://docs.python.org/2/library/logging.html}{Python \texttt{logging}
module}. Create a \texttt{logger} object and call methods on it to print
messages with different severities.}
\es{Para una solución de registro más flexible que no tiene que ser removido
antes de la publicación de la actividad, el uso del
\href{http://docs.python.org/2/library/logging.html}{módulo \texttt{logging} de
Python}. Crear un objeto \texttt{logger} y llamar a métodos en él para imprimir
mensajes con diferentes niveles de gravedad.}

\begin{frame}[fragile]
\frametitle{\en{Sugar logging}\es{Registro en Sugar}}
\begin{block}{\en{Log files}\es{Archivos de registro}}
{\large{\texttt{\textasciitilde/.sugar/default/logs/\en{activity.id}\es{actividad.id}-$N$.log}}}
\end{block}
\begin{block}{\en{Logging code}\es{Código de registro}}
\begin{lstlisting}[language=Python]
import logging

self._logger = logging.getLogger('nombre-de-mi-actividad')

self._logger.error('Este es un error')
self._logger.warning('...una advertencia')
self._logger.debug('...un mensaje de depuracion')
\end{lstlisting}
\end{block}
\end{frame}


\section{\en{Internationalisation}\es{Internationalisation}}

\en{Internationalisation is an important part of writing an activity, as it
allows your activity to be used in other languages. Internationalisation is
mostly about translation, but other things must be considered (such as
currencies, date formats, and whether text is written left-to-right or
right-to-left). Adding translation support to an activity is easier; the others
are more complex and are not covered here.}
\es{La internacionalización es una parte importante de la escritura una
actividad, ya que permite que la actividad que se utilizará en otros idiomas. La
internacionalización es sobre todo acerca de la traducción, pero otras cosas se
debe considerar (como monedas, formatos de fecha y si el texto se escribe de
izquierda a derecha o de derecha a izquierda). Adición de apoyo a la traducción
de una actividad es más fácil; los otros son más complejos y no están cubiertos
aquí.}

\en{To add translation support, a library called \texttt{gettext} is used. For
each UI string to be translated, the English string is passed through the
\texttt{\_} (underscore) function provided by \texttt{gettext}, which returns
either a translated version, or the original string if no translation is
available.}
\es{Para añadir soporte de traducción, se utiliza una librería llamada
\texttt{gettext}. Para cada cadena de IU sea traducida, la cadena de Inglés se
pasa a través de la función \texttt{\_} (guión bajo) proporcionado por
\texttt{gettext}, que devuelve una versión traducida, o la cadena original si no
hay traducción disponible.}

\begin{frame}[fragile]
\frametitle{\en{Translation support}\es{Apoyo a la traducción}}
\begin{lstlisting}[language=Python]
from gettext import gettext as _

# Previoso: Gtk.Button('Hello world!')
button = Gtk.Button(_('Hello world!'))
\end{lstlisting}
\end{frame}

\en{In addition to these code changes, a set of \texttt{.po} translation files
have to be created. These give the translations of the English strings into
other languages, one file per language. Each file is written manually by a human
translator, working from a \texttt{.pot} template file. This \texttt{.pot} file
must be periodically updated to reflect changes in the strings marked for
translation in the program code.}
\es{Además de estos cambios en el código, un conjunto de archivos de traducción
\texttt{.po} tienen que ser creados. Estos dan las traducciones de las cadenas
en Inglés a otros idiomas, un archivo por cada idioma. Cada archivo se escribe
manualmente por un traductor humano, trabajando desde un archivo de plantilla
\texttt{.pot}. Este archivo \texttt{.pot} debe actualizarse periódicamente para
reflejar los cambios en las cuerdas marcadas para la traducción en el código del
programa.}

\en{To generate the \texttt{.pot} file, run \texttt{./setup.py~genpot}. You can
then copy the \texttt{.pot} file to (for example) \texttt{es.po} and write the
Spanish translation. Don't forget to commit both files to git.}
\es{Para generar el archivo \texttt{.pot}, ejecutar \texttt{./setup.py~genpot}.
A continuación, puede copiar el archivo \texttt{.pot} a (por ejemplo)
\texttt{es.po} y escribir la traducción en Español. No te olvides de añadir los
dos archivos a git.}

\begin{frame}{\en{Generating a POT}\es{Generación de un POT}}
\begin{itemize}
    \item{\texttt{./setup.py genpot}}
    \item{\texttt{cd po}}
    \item{\texttt{cp \en{ActivityName}\es{NombreDeActividad}.pot es.po}}
    \item{\en{Edit \texttt{es.po} to create the Spanish translation.}
          \es{Editar \texttt{es.po} para crear la traducción en Español}}
\end{itemize}
\end{frame}

\note{Give an interactive example of generating a POT file and changing it to a
PO file now.}

\en{Activities whose source code is hosted on \url{http://git.sugarlabs.org} can
use a web-based service called Pootle to get translations from teams all over
the world. This is a valuable service, and more information about setting it up
is available online.}
\es{Actividades cuyo código está alojado en \url{http://git.sugarlabs.org}
pueden utilizar un servicio basado en web llamado Pootle para obtener
traducciones de los equipos de todo el mundo. Este es un servicio valioso, y más
información sobre su puesta en marcha está disponible en línea.}

\begin{frame}{\en{Adding Pootle support}\es{Añadir soporte de Pootle}}
\begin{block}{\en{Reference}\es{Referencía}}
\en{\url{http://en.flossmanuals.net/make-your-own-sugar-activities/going-international-with-pootle/}}
\es{\url{http://en.flossmanuals.net/como-hacer-una-actividad-sugar/internacionalizarse-con-pootle-god-100/}}
\end{block}
\begin{block}{\en{Overview}\es{Visión de conjunto}}
\begin{enumerate}
    \item{\en{Push activity code to git.sugarlabs.org, as described below.}
          \es{Empuje código de actividad a git.sugarlabs.org, tal como se
              describe a continuación.}}
    \item{\en{Allow the `pootle' user to commit to git.}
          \es{Permitir que el usuario `pootle' para crear commites en git.}}
    \item{\en{File a bug report requesting Pootle support for your project.}
          \es{Presentar un informe de error solicitando apoyo Pootle para su
              proyecto.}}
\end{enumerate}
\end{block}
\end{frame}


\section{\en{Publishing an activity}\es{Publicar una actividad}}

\en{After finishing the activity, testing it on relevant versions of the XO (in
emulation and on physical machines), and generating a \texttt{.xo} bundle, the
activity needs to be published to \url{http://activities.sugarlabs.org} for
users to download.}
\es{Después de terminar la escritura de la actividad, la probación en las
versiones pertinentes de la XO (en la emulación y en máquinas físicas), y la
generación de un paquete de \texttt{.xo}, la actividad tiene que ser publicada a
\url{http://activities.sugarlabs.org/es-ES/} para que los usuarios descargar.}

\en{Before publishing the activity, its source code must be made available on
\url{http://git.sugarlabs.org} so that others can view it and improve on it.
Educatrachos has \href{https://git.sugarlabs.org/+educatrachos}{a team page} on
that website, and anyone from Educatrachos who is writing an activity should
become a member of the team. An administrator (like me) can do that.}
\es{Antes de la publicación de la actividad, su código debe estar disponible en
\url{http://git.sugarlabs.org} para que otros puedan verlo y mejorar en él.
Educatrachos tiene
\href{https://git.sugarlabs.org/+educatrachos}{una página del equipo} en ese
sitio web, y cualquier persona de Educatrachos que está escribiendo una
actividad debe convertirse en un miembro del equipo. Un administrador (como yo)
puede hacer eso.}

\en{To add an activity to \url{http://git.sugarlabs.org}, add a new project for
it, then create a repository in that project. Name both after the activity. Once
the repository's been created, add it as a \texttt{remote} called
\texttt{origin} in your local git repository, then push the \texttt{master}
branch to it. Whenever you commit to the local repository from that point
onwards, you must subsequently push the commit to the remote so that it is
visible online.}
\es{Para añadir una actividad a \url{http://git.sugarlabs.org}, agregue un nuevo
proyecto para que, a continuación, crear un repositorio en ese proyecto. Nombra
dos después de la actividad. Después ha creado el repositorio, añadirlo como el
\texttt{remote} se llama \texttt{origin} en su repositorio git local, empujar la
rama \texttt{master} a ella. Cada vez que se crea un commit en el repositorio
local de ese punto en adelante, debe posteriormente empujar el commit con el
mando a distancia para que sea visible en Internet.}

\begin{frame}{\en{Publishing activity source code}
              \es{Publicación del código de una actividad}}
\begin{enumerate}
    \item{\en{Register on \href{http://git.sugarlabs.org}{git.sugarlabs.org}:}
          \es{Registrarse en
              \href{http://git.sugarlabs.org}{git.sugarlabs.org}:}
          \url{https://git.sugarlabs.org/users/new}}
    \item{\en{Have your account added to the Educatrachos team:}
          \es{Haga que su cuenta agregada al equipo Educatrachos:}
          \url{https://git.sugarlabs.org/+educatrachos/memberships/new}}
    \item{\en{Create a new project owned by the Educatrachos team:}
          \es{Crear un nuevo proyecto de propiedad del equipo Educatrachos:}
          \url{https://git.sugarlabs.org/projects/new}}
    \item{\en{Add a new repository to the project. Enable merge requests so
              others can suggest changes to the code.}
          \es{Añadir un nuevo repositorio para el proyecto. Permitir solicitudes
              de fusiones para que otros pueden sugerir cambios en el código.}}
    \item{\en{Copy the `SSH' URI from ``Clone \& push URLs'' on the repository
              page. e.g.\ \url{gitorious@git.sugarlabs.org:pascal-triangle/pascal-triangle.git}}
          \es{Copie el URI `SSH' desde ``Clone \& push URLs'' en la página del
              repositorio. Por ejemplo,
              \url{gitorious@git.sugarlabs.org:pascal-triangle/pascal-triangle.git}}}
    \item{\en{In a terminal:}\es{En un terminal:}
          \texttt{cd \en{path/to/my-activity}\es{camino/a/mi-actividad}}}
    \item{\texttt{git~remote add origin \emph{SSH URI}}}
    \item{\texttt{git~push -u origin master}}
\end{enumerate}
\end{frame}

\en{With the source code published online, the activity can be added to
\url{http://activities.sugarlabs.org}. You must register an account on that
website, then join the
\href{http://activities.sugarlabs.org/en-US/developers}{Developer Hub} and follow
the process to submit a new activity.}
\es{Con el código fuente publicada en línea, la actividad se puede añadir a
\url{http://activities.sugarlabs.org/es-ES/}. Debe registrar una cuenta en ese
sitio web, y luego unirse el Centro de Desarrollo y seguir el proceso para
enviar una nueva actividad.}

\en{Newly submitted activities are initially marked as private. Once enough
details have been filled out for an activity, it is moved to the sandbox, when
users can start downloading it. Once enough users have downloaded and rated the
activity, it can be peer-reviewed and promoted to public status.}
\es{Actividades recién enviados inicialmente se marcan como privados. Una vez
que suficientes detalles se han llenado de una actividad, se trasladó a la caja
de arena, cuando los usuarios pueden empezar a descargarlo. Una vez que
suficientes usuarios han descargado y evaluado la actividad, puede ser revisada
por pares y promovido a la condición pública.}

\begin{frame}{\en{Publishing an activity bundle}
              \es{Publicación de un paquete de una actividad}}
\begin{enumerate}
    \item{\en{Register on
              \href{http://activities.sugarlabs.org}{activities.sugarlabs.org}:
              \url{http://activities.sugarlabs.org/en-US/sugar/users/register}}
          \es{Registrarse en:
              \href{http://activities.sugarlabs.org/es-ES/}
                  {activities.sugarlabs.org}:
              \url{http://activities.sugarlabs.org/es-ES/sugar/users/register}}}
    \item{\en{Join the `Developer Hub':
              \url{http://activities.sugarlabs.org/en-US/developers}}
          \es{Únete a la `Centro de desarrolladores':
              \url{http://activities.sugarlabs.org/es-ES/developers}}}
    \item{\en{Follow the process to submit a new activity:
              \url{http://activities.sugarlabs.org/en-US/developers/addon/submit}}
          \es{Siga el proceso para enviar una nueva actividad:
              \url{http://activities.sugarlabs.org/es-ES/developers/addon/submit}}}
\end{enumerate}
\end{frame}


\section{\en{Conclusion}\es{Conclusión}}

\en{In summary: one of the key aims of writing your own activities should be to
work in partnership with the worldwide Sugar and OLPC community. This is
sometimes called ``working upstream''. They are happy to answer questions and
help solve problems, and in return they would be happy to receive new activities
and contributions which can be re-used by other OLPC deployments. As with any
community, the tighter people integrate, the better the results for everyone.}
\es{En resumen: uno de los objetivos principales de escribir sus propias
actividades debería ser trabajar en colaboración con la comunidad mundial de
Sugar y OLPC. Esto a veces se llama ``trabajando río arriba''. Ellos están
dispuestos a responder preguntas y ayudar a resolver problemas, y en cambio
estarían felices de recibir las nuevas actividades y las contribuciones que
pueden ser reutilizados por otros despliegues de OLPC. Al igual que con
cualquier comunidad, el pueblo más estrictas integran, mejores serán los
resultados para todos.}

\en{This is the end of the training, but not the end of the learning. I
encourage you to practice everything you've learned by writing activities. The
best way to learn programming is through practice. I am happy to answer
absolutely any questions either in person or by e-mail, even after I've left
Honduras. I would be thrilled to help get activities published by Educatrachos
once I return to the UK.}
\es{Este es el final de la capacitación, pero no el final del aprendizaje. Les
animo a practicar todo lo que has aprendido al escribir algunas actividades. La
mejor manera de aprender es a través de la práctica de programación. Estoy
encantado de responder a cualquier pregunta en absoluto, ya sea en persona o por
e-mail, incluso después de que me he dejado Honduras. Yo estaría encantado de
ayudar a que las actividades publicadas por Educatrachos cuando regreso al
Reino~Unido.}

\note{After a break, it would be a good idea to give an interactive demo of
creating an entire activity from scratch.}


\section{\en{Miscellany}\es{Miscelánea}}

\en{Again, not all the features of Sugar can be covered
in the available time. Here are the topics which haven't been covered, along
with links to relevant documentation. Writing activities in HTML5 wasn't covered
because the version of Sugar deployed in Honduras is too old to support them.}
\es{Una vez más, no todas las características de Sugar se pueden cubrir en el
tiempo disponible. Estos son los temas que no han sido cubiertos, así como
enlaces a la documentación pertinente. Las actividades de escritura en HTML5 no
estaba cubierto por la versión de Sugar desplegado en Honduras es demasiado
viejo para apoyarlos.}

\begin{frame}{\en{What's missing}\es{Temas no abarcados}}
\begin{itemize}
    \item{\en{Drawing custom widgets with Cairo:}
          \es{Dibujo widgets personalizados con Cairo:}
          % FIXME: This should actually be the following, but it doesn't exist yet:
          % https://developer.gnome.org/gnome-devel-demos/unstable/widget_drawing.py.html.en
          \href{http://tecnocode.co.uk/misc/platform-demos/widget_drawing.py.xhtml}{(1)},
          \href{http://www.tortall.net/mu/wiki/CairoTutorial}{(2)},
          \href{https://sites.google.com/site/randomcodecollections/home/python-gtk-3-pango-cairo-example}{(3)},
          \href{http://ptomato.name/advanced-gtk-techniques/html/custom-container.html}{(4)},
          \href{http://lotsofexpression.blogspot.com/2012/04/python-gtk-3-example-implementing-cairo.html}{(5)}}
    \item{\en{Shared activities:}\es{Actividades compartidas:}
          \en{\href{http://en.flossmanuals.net/make-your-own-sugar-activities/making-shared-activities/}{(1)}}
          \es{\href{http://en.flossmanuals.net/como-hacer-una-actividad-sugar/making-shared-activities-vc/}{(1)}}}
    \item{\en{Text-to-speech:}\es{Texto a voz:}
          \en{\href{http://en.flossmanuals.net/make-your-own-sugar-activities/adding-text-to-speech/}{(1)}}
          \es{\href{http://en.flossmanuals.net/como-hacer-una-actividad-sugar/adding-text-to-speach/}{(1)}}}
    \item{\en{Games with PyGame:}\es{Juegos con PyGame:}
          \en{\href{http://en.flossmanuals.net/make-your-own-sugar-activities/making-activities-using-pygame/}{(1)}}
          \es{\href{http://en.flossmanuals.net/como-hacer-una-actividad-sugar/construir-actividades-usando-pygame/}{(1)}}}
    \item{HTML5:
          \href{http://developer.sugarlabs.org/web-architecture.md.html}{(1)}}
\end{itemize}
\end{frame}


\begin{frame}{\en{Links}\es{Enlaces}}
\begin{block}{\en{Important links}\es{Enlaces importantes}}
\begin{itemize}
    \item{\en{\url{http://en.flossmanuals.net/make-your-own-sugar-activities/}}
          \es{\url{http://en.flossmanuals.net/como-hacer-una-actividad-sugar/heredar-activity-de-sugaractivity-jm-50/}}}
    \item{\url{http://python-gtk-3-tutorial.readthedocs.org/en/}}
    \item{\url{http://doc.sugarlabs.org/epydocs/}}
\end{itemize}
\end{block}
\begin{block}{\en{Other links}\es{Enlaces otros}}
\begin{itemize}
    \item{\url{http://wiki.sugarlabs.org/go/Features/GTK3/Porting}}
    \item{\url{http://wiki.sugarlabs.org/go/Human_Interface_Guidelines/The_Sugar_Interface}}
    \item{\url{http://wiki.sugarlabs.org/go/Development_Team/Almanac}}
    \item{\url{http://wiki.sugarlabs.org/go/Activity_Team}}
\end{itemize}
\end{block}
\end{frame}


\begin{frame}<presentation>{\en{Questions?}\es{¿Preguntas?}}
\en{Any questions so far?}
\es{¿Hay preguntas hasta ahora?}
\end{frame}