Subversion Repositories eFlore/Archives.cel-v2

Rev

Rev 31 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 31 Rev 36
1
package org.tela_botanica.client.vues;
1
package org.tela_botanica.client.vues;
2
 
2
 
3
import java.util.Iterator;
3
import java.util.Iterator;
4
 
4
 
5
import org.tela_botanica.client.image.ImageMediateur;
5
import org.tela_botanica.client.image.ImageMediateur;
6
import org.tela_botanica.client.interfaces.Rafraichissable;
6
import org.tela_botanica.client.interfaces.Rafraichissable;
7
import org.tela_botanica.client.interfaces.VueListable;
7
import org.tela_botanica.client.interfaces.VueListable;
8
import org.tela_botanica.client.modeles.ImageCarnet;
8
import org.tela_botanica.client.modeles.ImageCarnet;
9
import org.tela_botanica.client.modeles.ListeImageCarnet;
9
import org.tela_botanica.client.modeles.ListeImageCarnet;
10
 
10
 
11
import com.google.gwt.core.client.JavaScriptObject;
11
import com.google.gwt.core.client.JavaScriptObject;
12
import com.google.gwt.user.client.Window;
12
import com.google.gwt.user.client.Window;
13
import com.gwtext.client.core.EventObject;
13
import com.gwtext.client.core.EventObject;
14
import com.gwtext.client.core.Ext;
14
import com.gwtext.client.core.Ext;
15
import com.gwtext.client.core.ExtElement;
15
import com.gwtext.client.core.ExtElement;
16
import com.gwtext.client.core.JsObject;
16
import com.gwtext.client.core.JsObject;
17
import com.gwtext.client.data.ArrayReader;
17
import com.gwtext.client.data.ArrayReader;
18
import com.gwtext.client.data.FieldDef;
18
import com.gwtext.client.data.FieldDef;
19
import com.gwtext.client.data.IntegerFieldDef;
19
import com.gwtext.client.data.IntegerFieldDef;
20
import com.gwtext.client.data.MemoryProxy;
20
import com.gwtext.client.data.MemoryProxy;
21
import com.gwtext.client.data.Record;
21
import com.gwtext.client.data.Record;
22
import com.gwtext.client.data.RecordDef;
22
import com.gwtext.client.data.RecordDef;
23
import com.gwtext.client.data.Store;
23
import com.gwtext.client.data.Store;
24
import com.gwtext.client.data.StoreMgr;
24
import com.gwtext.client.data.StoreMgr;
25
import com.gwtext.client.data.StringFieldDef;
25
import com.gwtext.client.data.StringFieldDef;
26
import com.gwtext.client.util.JavaScriptObjectHelper;
26
import com.gwtext.client.util.JavaScriptObjectHelper;
27
import com.gwtext.client.widgets.BoxComponent;
27
import com.gwtext.client.widgets.BoxComponent;
28
import com.gwtext.client.widgets.Component;
28
import com.gwtext.client.widgets.Component;
29
import com.gwtext.client.widgets.Container;
29
import com.gwtext.client.widgets.Container;
30
import com.gwtext.client.widgets.Panel;
30
import com.gwtext.client.widgets.Panel;
31
import com.gwtext.client.widgets.event.ComponentListenerAdapter;
31
import com.gwtext.client.widgets.event.ComponentListenerAdapter;
32
import com.gwtext.client.widgets.event.ContainerListener;
32
import com.gwtext.client.widgets.event.ContainerListener;
33
import com.gwtext.client.widgets.event.ContainerListenerAdapter;
33
import com.gwtext.client.widgets.event.ContainerListenerAdapter;
34
import com.gwtext.client.widgets.event.PanelListener;
34
import com.gwtext.client.widgets.event.PanelListener;
35
import com.gwtext.client.widgets.event.PanelListenerAdapter;
35
import com.gwtext.client.widgets.event.PanelListenerAdapter;
36
import com.gwtext.client.widgets.grid.CellMetadata;
36
import com.gwtext.client.widgets.grid.CellMetadata;
37
import com.gwtext.client.widgets.grid.ColumnConfig;
37
import com.gwtext.client.widgets.grid.ColumnConfig;
38
import com.gwtext.client.widgets.grid.ColumnModel;
38
import com.gwtext.client.widgets.grid.ColumnModel;
39
import com.gwtext.client.widgets.grid.GridPanel;
39
import com.gwtext.client.widgets.grid.GridPanel;
40
import com.gwtext.client.widgets.grid.GridView;
40
import com.gwtext.client.widgets.grid.GridView;
41
import com.gwtext.client.widgets.grid.Renderer;
41
import com.gwtext.client.widgets.grid.Renderer;
42
import com.gwtext.client.widgets.grid.RowSelectionModel;
42
import com.gwtext.client.widgets.grid.RowSelectionModel;
43
import com.gwtext.client.widgets.grid.event.GridCellListener;
43
import com.gwtext.client.widgets.grid.event.GridCellListener;
44
import com.gwtext.client.widgets.grid.event.GridListener;
44
import com.gwtext.client.widgets.grid.event.GridListener;
45
import com.gwtext.client.widgets.grid.event.GridRowListener;
45
import com.gwtext.client.widgets.grid.event.GridRowListener;
46
import com.gwtext.client.widgets.grid.event.RowSelectionListener;
46
import com.gwtext.client.widgets.grid.event.RowSelectionListener;
47
import com.gwtext.client.widgets.grid.event.RowSelectionListenerAdapter;
47
import com.gwtext.client.widgets.grid.event.RowSelectionListenerAdapter;
48
import com.gwtext.client.widgets.layout.AnchorLayout;
48
import com.gwtext.client.widgets.layout.AnchorLayout;
49
import com.gwtext.client.widgets.layout.FitLayout;
49
import com.gwtext.client.widgets.layout.FitLayout;
50
import com.gwtextux.client.data.BufferedStore;
50
import com.gwtextux.client.data.BufferedStore;
51
 
51
 
52
/**
52
/**
53
 * Liste d'image composée de miniatures et d'information sur l'image
53
 * Liste d'image composée de miniatures et d'information sur l'image, implémente
-
 
54
 * l'interface rafraichissable et l'interface vueListable
54
 * 
55
 * 
55
 * @author aurelien
56
 * @author aurelien
56
 */
57
 */
57
public class ListeImageVue extends GridPanel implements Rafraichissable,
58
public class ListeImageVue extends GridPanel implements Rafraichissable,
58
		VueListable {
59
		VueListable {
-
 
60
 
59
 
61
	/**
-
 
62
	 * Le médiateur associé à la vue
60
	// instance du médiateur
63
	 */
61
	private ImageMediateur	iMediateur		= null;
64
	private ImageMediateur	iMediateur		= null;
-
 
65
	
-
 
66
	/**
-
 
67
	 * Config de colonne
62
 
68
	 */
-
 
69
	private ColumnConfig	numImage;
-
 
70
	/**
-
 
71
	 * Config de colonne
63
	private ColumnConfig	numImage;
72
	 */
-
 
73
	private ColumnConfig	urlImage;
-
 
74
	/**
-
 
75
	 * Config de colonne
64
	private ColumnConfig	urlImage;
76
	 */
-
 
77
	private ColumnConfig	lieImage;
-
 
78
	/**
-
 
79
	 * Config de colonne
65
	private ColumnConfig	lieImage;
80
	 */
-
 
81
	private ColumnConfig	datImage;
-
 
82
	/**
-
 
83
	 * Config de colonne
66
	private ColumnConfig	datImage;
84
	 */
-
 
85
	private ColumnConfig	appImage;
-
 
86
	/**
-
 
87
	 * Modele de colonnes
67
	private ColumnConfig	appImage;
88
	 */
-
 
89
	private ColumnModel		modeleColonnes;
-
 
90
 
-
 
91
	/**
68
	private ColumnModel		modeleColonnes;
92
	 * Booleen d'instanciation
69
 
93
	 */
70
	private boolean			estInstancie	= false;
94
	private boolean			estInstancie	= false;
-
 
95
 
71
 
96
	/**
-
 
97
	 * Store qui contient les données à afficher
-
 
98
	 */
-
 
99
	private Store			st				= null;
72
	// données locales
100
	/**
-
 
101
	 * Configuration des colonnes du store
-
 
102
	 */
-
 
103
	private ColumnConfig	cl				= null;
73
	// store qui gère les données de la liste d'images
104
	
-
 
105
	/**
-
 
106
	 * Barre de pagination
-
 
107
	 */
-
 
108
	private pageToolBarVue bt = null ;
-
 
109
 
-
 
110
	/**
-
 
111
	 * Constructeur sans arguments (privé car ne doit pas être utilisé)
-
 
112
	 */
-
 
113
	private ListeImageVue()
-
 
114
	{
-
 
115
		super() ;
-
 
116
	}
74
	private Store			st				= null;
117
	
75
	private ColumnConfig	cl				= null;
118
	/**
76
	
119
	 * Constructeur avec argument
77
	private pageToolBarVue bt = null ;
-
 
-
 
120
	 * @param im le médiateur à associer
78
 
121
	 */
-
 
122
	public ListeImageVue(ImageMediateur im) {
79
	public ListeImageVue(ImageMediateur im) {
123
 
80
 
124
		new ListeImageVue() ;
81
		super();
125
 
82
 
126
		this.setId("listeImageGrid");
83
		this.setId("listeImageGrid");
127
		// on associe le médiateur
84
 
128
		this.iMediateur = im;
85
		this.iMediateur = im;
129
		
86
		
130
		// on place la barre de pagination
87
		bt = new pageToolBarVue(im);		
131
		bt = new pageToolBarVue(im);		
88
		this.setBottomToolbar(bt) ;
132
		this.setBottomToolbar(bt) ;
-
 
133
 
89
 
134
		// on construit le modèle de colonnes
90
		numImage = new ColumnConfig("numéro", "num_image", 30, true);
135
		numImage = new ColumnConfig("numéro", "num_image", 30, true);
91
		datImage = new ColumnConfig("date", "dat_image", 120, true);
136
		datImage = new ColumnConfig("date", "dat_image", 120, true);
92
		lieImage = new ColumnConfig("lieu", "lie_image", 120, true);
137
		lieImage = new ColumnConfig("lieu", "lie_image", 120, true);
93
		appImage = new ColumnConfig("appareil", "app_image", 200, true);
138
		appImage = new ColumnConfig("appareil", "app_image", 200, true);
-
 
139
		// la colonne url possède une méthode de rendu spéciale
94
		urlImage = new ColumnConfig("Image", "url_image_S", 30, true,
140
		urlImage = new ColumnConfig("Image", "url_image_S", 30, true,
95
				new Renderer() {
141
				new Renderer() {
96
 
142
 
97
					public String render(Object value,
143
					public String render(Object value,
98
							CellMetadata cellMetadata, Record record,
144
							CellMetadata cellMetadata, Record record,
99
							int rowIndex, int colNum, Store store) {
145
							int rowIndex, int colNum, Store store) {
100
 
-
 
-
 
146
						// on affiche une div contenant l'image pointée par l'url
101
						String ImgUrl = record.getAsString("url_image_S");
147
						String ImgUrl = record.getAsString("url_image_S");
102
						String ImgNum = record.getAsString("num_image");
148
						String ImgNum = record.getAsString("num_image");
103
						return "<div class=\"img-list\"> <img src=\"" + ImgUrl
149
						return "<div class=\"img-list\"> <img src=\"" + ImgUrl
104
								+ "\" title='" + ImgNum + "'> </div>";
150
								+ "\" title='" + ImgNum + "'> </div>";
105
					}
151
					}
106
 
152
 
107
				});
153
				});
108
 
154
		
-
 
155
		// on associe le modèle de colonnes
109
		ColumnConfig[] cm = {numImage, urlImage, datImage, lieImage, appImage};
156
		ColumnConfig[] cm = {numImage, urlImage, datImage, lieImage, appImage};
110
		modeleColonnes = new ColumnModel(cm);
157
		modeleColonnes = new ColumnModel(cm);
111
		this.setColumnModel(modeleColonnes);
158
		this.setColumnModel(modeleColonnes);
112
		this.setAutoScroll(true);
159
		this.setAutoScroll(true);
113
		this.setAutoWidth(true);
160
		this.setAutoWidth(true);
114
		this.setEnableColumnResize(true);
161
		this.setEnableColumnResize(true);
115
 
162
 
116
		// creation du store
163
		// creation du store
117
		FieldDef defNumImage = new IntegerFieldDef("num_image");
164
		FieldDef defNumImage = new IntegerFieldDef("num_image");
118
		FieldDef defDatImage = new StringFieldDef("dat_image");
165
		FieldDef defDatImage = new StringFieldDef("dat_image");
119
		FieldDef defLieImage = new StringFieldDef("lie_image");
166
		FieldDef defLieImage = new StringFieldDef("lie_image");
120
		FieldDef defAppImage = new StringFieldDef("app_image");
167
		FieldDef defAppImage = new StringFieldDef("app_image");
121
		FieldDef defUrlImageS = new StringFieldDef("url_image_S");
168
		FieldDef defUrlImageS = new StringFieldDef("url_image_S");
122
		FieldDef defUrlImageM = new StringFieldDef("url_image_M");
169
		FieldDef defUrlImageM = new StringFieldDef("url_image_M");
123
		FieldDef defUrlImage = new StringFieldDef("url_image");
170
		FieldDef defUrlImage = new StringFieldDef("url_image");
124
		FieldDef[] defTab = { defNumImage, defDatImage, defLieImage,
171
		FieldDef[] defTab = { defNumImage, defDatImage, defLieImage,
125
				defAppImage, defUrlImageS, defUrlImageM, defUrlImage };
172
				defAppImage, defUrlImageS, defUrlImageM, defUrlImage };
126
		RecordDef rd = new RecordDef(defTab);
173
		RecordDef rd = new RecordDef(defTab);
127
		st = new Store(rd);
174
		st = new Store(rd);
-
 
175
		// on associe le store
128
		this.setStore(st);
176
		this.setStore(st);
129
		this.getView().setAutoFill(true);
177
		this.getView().setAutoFill(true);
130
 
178
		
-
 
179
		// on crée un masque de chargement qui s'affichera lors des mises à jour
131
		this.setLoadMask("chargement");
180
		this.setLoadMask("chargement");
-
 
181
 
132
 
182
		// on ajoute les listeners
133
		ajouterListeners();
183
		ajouterListeners();
134
 
184
 
135
	}
185
	}
-
 
186
 
-
 
187
	/**
-
 
188
	 * Ajoute les listeners pour la gestion des évènements
136
 
189
	 */
137
	public void ajouterListeners() {
190
	private void ajouterListeners() {
138
		this.addListener(new ContainerListenerAdapter() {
191
		this.addListener(new ContainerListenerAdapter() {
139
 
192
 
140
			public void onHide(Component component) {
193
			public void onHide(Component component) {
141
 
194
 
142
			}
195
			}
-
 
196
 
143
 
197
			// lors du premier rendu on demande les données qui sont déjà contenues dans la galerie qui est le premier élément affiché 
144
			public void onRender(Component component) {
198
			public void onRender(Component component) {
145
 
199
 
146
				if (!isEstInstancie()) {
200
				if (!isEstInstancie()) {
147
					setEstInstancie(true);
201
					setEstInstancie(true);
148
					getIMediateur().synchroniserSelection("galerie");
202
					getIMediateur().synchroniserSelection("galerie");
149
				}
203
				}
150
			}
204
			}
151
 
205
 
152
			public void onShow(Component component) {
206
			public void onShow(Component component) {
153
 
207
 
154
			}
208
			}
155
 
209
 
156
		});
210
		});
157
 
211
 
158
		this.addGridRowListener(new GridRowListener() {
212
		this.addGridRowListener(new GridRowListener() {
159
 
213
			
-
 
214
			// gestion du clic sur une ligne
160
			public void onRowClick(GridPanel grid, int rowIndex, EventObject e) {
215
			public void onRowClick(GridPanel grid, int rowIndex, EventObject e) {
-
 
216
 
161
 
217
				// on notifie le médiateur et on lui passe le nuémro de ligne
162
				getIMediateur().clicListeImage(rowIndex);
218
				getIMediateur().clicListeImage(rowIndex);
163
			}
219
			}
-
 
220
			
164
 
221
			// gestion du clic droit
165
			public void onRowContextMenu(GridPanel grid, int rowIndex,
222
			public void onRowContextMenu(GridPanel grid, int rowIndex,
166
					EventObject e) {
-
 
-
 
223
					EventObject e) {
167
 
224
				// on stoppe l'évenement pour empecher le navigateur d'afficher son propre menu
-
 
225
				e.stopEvent() ;
168
				e.stopEvent() ;
226
				// on notifie le médiateur en lui passant l'évenement
169
				getIMediateur().montrerContextMenu(e);
227
				getIMediateur().montrerContextMenu(e);
170
			}
228
			}
-
 
229
 
171
 
230
			// gestion du double clic
172
			public void onRowDblClick(GridPanel grid, int rowIndex,
231
			public void onRowDblClick(GridPanel grid, int rowIndex,
173
					EventObject e) {
-
 
-
 
232
					EventObject e) {
174
 
233
				// on notifie le médiateur en lui passant le numéro de ligne
175
				getIMediateur().doubleClicListeImage(rowIndex);
234
				getIMediateur().doubleClicListeImage(rowIndex);
176
			}
235
			}
177
		});
236
		});
178
 
237
 
179
		this.getSelectionModel().addListener(new RowSelectionListenerAdapter() {
238
		this.getSelectionModel().addListener(new RowSelectionListenerAdapter() {
-
 
239
 
180
 
240
			// gestion de la sélection
-
 
241
			public void onSelectionChange(RowSelectionModel sm) {
181
			public void onSelectionChange(RowSelectionModel sm) {
242
 
-
 
243
				// si on a rien de sélectionné
182
 
244
				if (sm.getCount() <= 0) {
183
				if (sm.getCount() <= 0) {
245
					// on notifie le médiateur (qui désactive notamment l'accès à certaines infos)
-
 
246
					getIMediateur().aucuneSelection();
184
					getIMediateur().aucuneSelection();
247
				} else {
-
 
248
					// sinon on notifie le médiateur
185
				} else {
249
					getIMediateur().selection();
186
					getIMediateur().selection();
250
					// et on lui demande de synchroniser la selection avec les autres vues
187
					getIMediateur().synchroniserSelection("liste");
251
					getIMediateur().synchroniserSelection("liste");
188
				}
252
				}
189
			}
253
			}
190
		});
254
		});
191
	}
255
	}
-
 
256
 
192
 
257
	/**
193
	public ColumnConfig getCl() {
258
	 * Méthode héritée de l'interface VueListable
194
		return cl;
259
	 * Sélectionne les images dans la galerie suivant les identifiants donnés en paramètres
195
	}
-
 
196
 
260
	 */
197
	public String[] getIdSelectionnees() {
261
	public String[] getIdSelectionnees() {
198
		Record[] selection = this.getSelectionModel().getSelections();
262
		Record[] selection = this.getSelectionModel().getSelections();
199
		int taille = selection.length;
263
		int taille = selection.length;
200
		String id_selection[] = new String[taille];
264
		String id_selection[] = new String[taille];
201
 
265
 
202
		for (int i = 0; i < selection.length; i++) {
266
		for (int i = 0; i < selection.length; i++) {
203
 
267
 
204
			id_selection[i] = selection[i].getAsString("num_image");
268
			id_selection[i] = selection[i].getAsString("num_image");
205
		}
269
		}
206
 
270
 
207
		return id_selection;
271
		return id_selection;
208
	}
272
	}
-
 
273
 
-
 
274
	/**
-
 
275
	 * Accesseur pour la config de colonnes
-
 
276
	 * @return la config de colonnes
-
 
277
	 */
-
 
278
	public ColumnConfig getCl() {
-
 
279
		return cl;
-
 
280
	}
-
 
281
	
-
 
282
	/**
-
 
283
	 * Accesseur pour le médiateur
-
 
284
	 * @return le médiateur associé
209
 
285
	 */
210
	public ImageMediateur getIMediateur() {
286
	public ImageMediateur getIMediateur() {
211
		return iMediateur;
287
		return iMediateur;
212
	}
288
	}
-
 
289
 
-
 
290
	/**
-
 
291
	 * Accesseur pour le modèle de colonnes
-
 
292
	 * @return le modèle de colonnes
213
 
293
	 */
214
	public ColumnModel getModeleColonnes() {
294
	public ColumnModel getModeleColonnes() {
215
		return modeleColonnes;
295
		return modeleColonnes;
216
	}
296
	}
-
 
297
 
217
 
298
	/**
218
	public ColumnConfig getNumImage() {
299
	 * Accesseur pour le store
219
		return numImage;
300
	 * @return le store contenant les données
220
	}
-
 
221
 
301
	 */
222
	public Store getSt() {
302
	public Store getSt() {
223
		return st;
303
		return st;
224
	}
304
	}
225
 
305
	
226
	public ColumnConfig getUrlImage() {
-
 
227
		return urlImage;
-
 
228
	}
-
 
229
 
-
 
230
	/**
306
	/**
-
 
307
	 * Accesseur pour le booleen d'instanciation
231
	 * @return the estInstancie
308
	 * @return le booleen d'instanciation
232
	 */
309
	 */
233
	public boolean isEstInstancie() {
310
	public boolean isEstInstancie() {
234
		return estInstancie;
311
		return estInstancie;
235
	}
312
	}
-
 
313
 
-
 
314
	/**
-
 
315
	 * Méthode héritée de l'interface rafraichissable
-
 
316
	 * @param nouvelleDonnees les nouvelles données
-
 
317
	 * @param repandreRafraichissement le booleen de notification du rafraichissement
236
 
318
	 */
237
	public void rafraichir(Object nouvelleDonnees,
319
	public void rafraichir(Object nouvelleDonnees,
238
			boolean repandreRafraichissement) {
320
			boolean repandreRafraichissement) {
-
 
321
 
239
 
322
		// si on reçoit un store
-
 
323
		if (nouvelleDonnees instanceof Store) {
240
		if (nouvelleDonnees instanceof Store) {
324
 
241
 
325
			// on affecte celui-ci comme gestionnaire de données
-
 
326
			st = (Store) nouvelleDonnees;
242
			st = (Store) nouvelleDonnees;
327
			st.load();
243
			st.load();
328
			// et on reconfigure et rafraichit la vue
244
			this.reconfigure(st, this.getColumnModel());
329
			this.reconfigure(st, this.getColumnModel());
245
					
330
					
246
		}
331
		}
-
 
332
 
247
 
333
		// si on doit répandre l'évenement
-
 
334
		if (repandreRafraichissement) {
248
		if (repandreRafraichissement) {
335
			// on notifie le médiateur avec une copie des données
249
			getIMediateur().synchroniserDonneesZoomListeGalerie(
336
			getIMediateur().synchroniserDonneesZoomListeGalerie(
250
					nouvelleDonnees, this);
337
					nouvelleDonnees, this);
251
		}
338
		}
252
	}
339
	}
-
 
340
 
-
 
341
	/**
-
 
342
	 * Sélectionne des enregistrements donné 
-
 
343
	 * @param sel un tableau d'enregistrement à selectionner
253
 
344
	 */
254
	public void selectionnerEnregistrements(Record[] sel) {
345
	public void selectionnerEnregistrements(Record[] sel) {
255
 
346
 
256
		if (isEstInstancie()) {
347
		if (isEstInstancie()) {
257
			getSelectionModel().clearSelections();
348
			getSelectionModel().clearSelections();
258
			getSelectionModel().selectRecords(sel);
349
			getSelectionModel().selectRecords(sel);
259
		}
350
		}
260
	}
351
	}
-
 
352
	
-
 
353
	/**
-
 
354
	 * Accesseur pour la toolbar de pagination
-
 
355
	 * @return la toolbar de pagination
261
	
356
	 */
262
	public pageToolBarVue getToolBarVue()
357
	public pageToolBarVue getToolBarVue()
263
	{
358
	{
264
		return bt ;
359
		return bt ;
265
	}
360
	}
266
 
361
 
267
	/**
362
	/**
268
	 * @param estInstancie
363
	 * Setteur pour le booleen d'instanciation
269
	 *            the estInstancie to set
364
	 * @param estInstancie la nouvelle valeur du booleen
270
	 */
365
	 */
271
	public void setEstInstancie(boolean estInstancie) {
366
	public void setEstInstancie(boolean estInstancie) {
272
		this.estInstancie = estInstancie;
367
		this.estInstancie = estInstancie;
273
	}
368
	}
274
 
-
 
275
	/**
-
 
276
	 * @param mediateur
-
 
277
	 *            the iMediateur to set
-
 
278
	 */
-
 
279
	public void setIMediateur(ImageMediateur mediateur) {
-
 
280
		iMediateur = mediateur;
-
 
281
	}
-
 
282
 
369
 
283
}
370
}