diff --git a/src/About.java b/src/About.java new file mode 100644 index 0000000..480b0ce --- /dev/null +++ b/src/About.java @@ -0,0 +1,214 @@ + + +/* + * aNNiMON 2010 + * For more info visit http://annimon.com/ + */ + +/* + * На основе класса MultiLineText от А.С. Ледкова + * www.mobilab.ru + */ + +import java.io.DataInputStream; +import java.util.Vector; +import javax.microedition.lcdui.*; + +public class About extends Canvas { + + private Font defaultFont; + private Displayable dspl; + private int fontHeight, defaultFontHeight; + private String text; //текст + + private int w, h; //размеры + + private int workingHeight; //Размер ограничивающего прямоугольника; + private int yBase; //Положение верхнего края текста + private int scrollStep; //Шаг при прокрутке текста + private int allTextHeight; //Общая высота текста + private Vector strLines; + + public About(Displayable dspl) { + setFullScreenMode(true); + this.dspl = dspl; + w = getWidth(); + h = getHeight(); + text = getText("/lang/about_"+Rms.languageApp); + fontHeight = UI.getSoftBarHeight()+2; + defaultFont = Font.getDefaultFont(); + scrollStep = defaultFontHeight = defaultFont.getHeight()+2; + workingHeight = h - fontHeight*2 - 2; + setParameters(); + } + + protected void sizeChanged(int w, int h) { + this.w = w; + this.h = h; + workingHeight = h - fontHeight*2 - 2; + setParameters(); + } + + + protected void paint(Graphics g) { + g.setColor(P.backgrnd); + g.fillRect(0, 0, w, h); + UI.drawTitle(g, L.str[L.about]); + g.setColor(P.fmtextnc); + g.setFont(defaultFont); + g.setClip(0, fontHeight+1, w, workingHeight); + int y1 = yBase; + for (int i = 0; i < strLines.size(); i++) { + if ((y1 + defaultFontHeight) > 0) { + g.drawString(strLines.elementAt(i).toString(), 1, fontHeight + 5 + y1, Graphics.LEFT | Graphics.TOP); + } + y1 = y1 + defaultFontHeight; + if (y1 > workingHeight) { + break; + } + } + g.setClip(0, 0, w, h); + UI.drawSoftBar(g, "", L.str[L.back]); + } + + protected void keyPressed(int key) { + int ga = getGameAction(key); + if(ga==UP) MoveUp(); + else if(ga==DOWN) MoveDown(); + else if(ga==LEFT) PageUp(); + else if(ga==RIGHT) PageDown(); + else if(ga==FIRE || key==Key.rightSoftKey) Main.dsp.setCurrent(dspl); + else if(key==Key.leftSoftKey) { + System.gc(); + } + repaint(); + } + + protected void keyRepeated(int key) { + keyPressed(key); + } + + /** + * Установка необходимых параметров для текста + */ + private void setParameters() { + //Разбиваем строку на массив строк + strLines = new Vector(); + String[] arr = splitString(text, "\n"); + for(int i = 0; i w) {//Слово полностью не умещается в строке + space = i0; + while (jw > w) { + j = 0; + while (j < w) { + space++; + j = defaultFont.stringWidth(substr.substring(in, space)); + } + space = space - 1; + j = defaultFont.stringWidth(substr.substring(in, space)); + strLines.addElement(substr.substring(in, space)); + jw = jw - j; + i0 = space; + in = space; + } + jw = 0; + } else { + i0 = space; + } + } + } + strLines.addElement(substr.substring(in, imax)); + } + allTextHeight = strLines.size() * defaultFontHeight; + } + + private void MoveDown() { + if (allTextHeight > workingHeight) { + yBase = yBase - scrollStep; + if (workingHeight - yBase > allTextHeight) { + yBase = workingHeight - allTextHeight; + } + } + } + + private void MoveUp() { + if (allTextHeight > workingHeight) { + yBase = yBase + scrollStep; + if (yBase > 0) { + yBase = 0; + } + } + + } + + private void PageUp() { + if (allTextHeight > workingHeight) { + yBase = yBase + workingHeight; + if (yBase > 0) { + yBase = 0; + } + } + + } + + private void PageDown() { + if (allTextHeight > workingHeight) { + yBase = yBase - workingHeight; + if (workingHeight - yBase > allTextHeight) { + yBase = workingHeight - allTextHeight; + } + } + } + + private String[] splitString(String str, String delim) { + if (str.length() == 0 || delim.length() == 0) return new String[]{str}; + + Vector v = new Vector(); + int pos = 0; + int newpos = str.indexOf(delim, 0); + + while (newpos != -1) { + v.addElement(str.substring(pos, newpos)); + pos = newpos + delim.length(); + newpos = str.indexOf(delim, pos); + } + v.addElement(str.substring(pos)); + + String[] s = new String[v.size()]; + v.copyInto(s); + return s; + } + + private String getText(String path) { + DataInputStream dis = new DataInputStream(getClass().getResourceAsStream(path)); + StringBuffer strBuff = new StringBuffer(); + int ch = 0; + try { + while ((ch = dis.read()) != -1) { + strBuff.append(StringEncoder.decodeCharCP1251((byte)ch)); + } + dis.close(); + } catch (Exception e) {e.printStackTrace();} + return strBuff.toString(); + } +} diff --git a/src/FWCashe.java b/src/FWCashe.java new file mode 100644 index 0000000..20a2b97 --- /dev/null +++ b/src/FWCashe.java @@ -0,0 +1,64 @@ + + +import javax.microedition.lcdui.Font; +import java.util.Vector; + +/** + * Класс кэша ширины букв шрифта + */ +public class FWCashe { + + /** + * Получить кэш + * @param font шрифт, из которого получаем кэш ширины букв + * @return экземпляр класса + */ + public static FWCashe getCache(Font font) { + Vector fwc = new Vector(); + Vector fwc_f = new Vector(); + for (int i = 0; i < fwc.size(); i++) { + if (fwc_f.elementAt(i).equals(font)) { + return (FWCashe) fwc.elementAt(i); + } + } + fwc_f.addElement(font); + FWCashe f = new FWCashe(font); + fwc.addElement(f); + return f; + } + + protected Font font; + protected byte[][] caches; + + protected FWCashe(Font font) { + this.font = font; + caches = new byte[256][]; + for (int i = 0; i < 256; i++) { + caches[i] = null; + } + } + + public int charWidth(char ch) { + int hi = (ch >> 8) & 0xFF; + int lo = (ch) & 0xFF; + if (caches[hi] == null) { + caches[hi] = new byte[256]; + for (int i = 0; i < 256; i++) { + caches[hi][i] = -1; + } + } + if (caches[hi][lo] == -1) { + caches[hi][lo] = (byte) font.charWidth(ch); + } + return caches[hi][lo]; + } + + public int stringWidth(String s) { + int width = 0; + int len = s.length(); + for (int i = 0; i < len; i++) { + width += charWidth(s.charAt(i)); + } + return width; + } +} diff --git a/src/FileManager.java b/src/FileManager.java new file mode 100644 index 0000000..46ce4be --- /dev/null +++ b/src/FileManager.java @@ -0,0 +1,479 @@ +import java.util.*; +import javax.microedition.lcdui.*; +import midedit.CompositionForm; +import midedit.MixerMain; +import midedit.io.AbstractFile; + +/** + * Файловый менеджер + * Используется для открытия и сохранения файлов + * + * @author aNNiMON + */ +public class FileManager extends Canvas { + + /* Расширения для групп данных */ + /** MIDI-файлы */ + private static final String[] TypeMid = { + "mid", "midi" + }; + + /** Высота шрифта */ + private static final int FONT_HEIGHT = P.smBold.getHeight()+2; + /** Высота курсора */ + private static final int SH_HEIGHT = FONT_HEIGHT + 1; + + + /** Путь к папке */ + public String pathFile; + + /** Размер экрана */ + private int w, h; + + /** Экран, в который попадаем при нажатии Отмена*/ + private Displayable previousDisplayable; + + /** Кэш ширины букв для маленького жирного шрифта */ + private FWCashe fontCashe; + + /** Файловая система */ + private AbstractFile file; + + /** Изображения и иконки групп файлов */ + //private Image folderIcon, imageIcon, fileIcon, fontIcon, videoIcon; + + /** Список файлов и папок */ + private String[] data; + /** Список пунктов меню */ + private String[] menu; + + /* Переменные для расчета координат вывода списка файлов */ + private int CursorY, startPrintFile, numFiles; + + /** Размеры и координаты вывода панели меню */ + private int menuY, menuWidth, menuHeight; + + /** Выбранный пункт в списке файлов и меню */ + private int curFiles, curMenu; + + /** Отображать ли меню */ + private boolean showMenu; + + /** + * Конструктор для открытия файлов + * @param s стартовый путь к папке + * @param aFile фс + */ + public FileManager(String s, AbstractFile aFile) { + setFullScreenMode(true); + w = getWidth(); + h = getHeight(); + + pathFile = s; + file = aFile; + + fontCashe = FWCashe.getCache(P.smBold); + CursorY = startPrintFile = curFiles = numFiles = 0; + showMenu = false; + + loadImages(); + // Список пунктов меню + menu = new String[] { + L.str[L.open], + L.str[L.play], + L.str[L.cancel] + }; + + update(); + } + + /** + * Конструктор для сохранения + * @param s путь к папке + * @param prev экран, куда вернёмся после отмены + * @param aFile фс + */ + public FileManager(String s, Displayable prev, AbstractFile aFile) { + this(s, aFile); + previousDisplayable = prev; + // меню сохранения + menu = new String[] { + L.str[L.saveInThisFolder], + // L.str[L.newFolder], + L.str[L.cancel] + }; + } + + /** + * Показать экран файлменеджера и при необходимости обновить список файлов + * @param update обновить список файлов + */ + public void setCurrent(boolean update) { + if(update) update(); + Main.dsp.setCurrent(this); + } + + /** Задать список файлов в меню */ + private void setMenu() { + Vector vt = new Vector(); + if (menu[0].equals(L.str[L.saveInThisFolder])) { + // Пункты при сохранении + vt.addElement(L.str[L.saveInThisFolder]); + //vt.addElement(L.str[L.newFolder]); + } else { + // Пункты при открытии + vt.addElement(L.str[L.open]); + if (getType(TypeMid, data[curFiles])) { + vt.addElement(L.str[L.play]); + //vt.addElement(L.str[L.openToBuffer]); + } + } + vt.addElement(L.str[L.cancel]); + menu = new String[vt.size()]; + vt.copyInto(menu); + vt = null; + + // Расчитываем размеры и координаты панели меню + calcMenuPos(); + } + + /** + * Вычисляем размеры и координаты панели меню + */ + private void calcMenuPos() { + menuHeight = FONT_HEIGHT * menu.length; + menuWidth = 0; + for(int i = 0; i < menu.length; i++) { + int itemWidth = fontCashe.stringWidth(menu[i]); + if(itemWidth > menuWidth) menuWidth = itemWidth; + } + menuWidth = menuWidth + 3; // Увеличиваем ширину, чтоб уж наверняка + menuY = h - menuHeight - UI.getSoftBarHeight(); + } + + protected void sizeChanged(int w, int h) { + this.w = getWidth(); + this.h = getHeight(); + super.sizeChanged(w, h); + } + + protected void paint(Graphics g) { + g.setColor(P.backgrnd); + g.fillRect(0, 0, w, h); + drawFiles(g); + if (showMenu) { + drawMenu(g); + } + UI.drawTitle(g, pathFile); + UI.drawSoftBar(g,L.str[L.menu],L.str[L.back]); + } + + /** + * Отрисовка списка файлов + * @param g контекст графики + */ + private void drawFiles(Graphics g) { + if (numFiles > 0) { + // Рисуем курсор + g.setColor(P.obv); + g.fillRect(0, CursorY + SH_HEIGHT, w, FONT_HEIGHT); + g.setColor(P.fmbord); + g.drawRect(0, CursorY + FONT_HEIGHT, w, FONT_HEIGHT); + } + int FileY = 0; + g.setFont(P.smBold); + for (int i = startPrintFile; i < numFiles; i++) { + // Иконка типа файла + /*Image tmp = fileIcon; + if (data[i].indexOf("/") != -1) tmp = folderIcon; + else if (getType(TypeMid, data[i])) tmp = imageIcon; + g.drawImage(tmp, 1, FileY + SH_HEIGHT + 1, 0);*/ + // Текст + int col = P.fmtextnc; + if (FileY == CursorY) col = P.fmtextcur; + g.setColor(col); + g.drawString(data[i], 18, FileY + SH_HEIGHT, 20); + + FileY += FONT_HEIGHT; + if(FileY > (h - (SH_HEIGHT*2)-3)) break; + } + } + + /** + * Отрисовка меню + * @param g контекст графики + */ + private void drawMenu(Graphics g) { + final int menuX = 3; + + g.setFont(P.smPlain); + int colorBack, colorObv, colorText; + // Отрисовуем пункты меню + for (int i = 0; i < menu.length; i++) { + // Для курсора используются другие цвета + if (i == curMenu) { + colorBack = P.fmbord; + colorObv = P.fmcurbord; + colorText = P.fmtextuppan; + } else { + colorBack = P.fmback1; + colorObv = P.obv; + colorText = P.fmcurbord; + } + int hh = menuY + i * (FONT_HEIGHT - 1); + g.setColor(colorBack); + g.fillRect(menuX, hh, menuWidth, FONT_HEIGHT - 1); + g.setColor(colorObv); + g.drawRect(menuX, hh, menuWidth, FONT_HEIGHT - 1); + g.setColor(colorText); + g.drawString(menu[i], menuX + 3, hh + 1, 20); + } + } + + /** + * Обработка выбранных пунктов + * @param selected ID выбранного пункта меню + */ + private void selectItem(int selected) { + // Выбранный пункт меню + final String cur = menu[selected]; + // Выбранный пункт в списке файлов + final String fileSelected = data[curFiles]; + + curMenu = 0; + showMenu = false; + + if (cur.equals(L.str[L.open])) { + // Открыть + nextDir(fileSelected); + P.path = pathFile; + } + else if (cur.equals(L.str[L.play])) { + // Проигрывание + /*if (getType(TypeMid, fileSelected)) { + Image img = JSR75.getImage(pathFile, fileSelected); + PPM.midlet.imgname = fileSelected.substring(0, fileSelected.lastIndexOf('.')); + PPM.dsp.setCurrent(new Viewer(img, this)); + } else if (getType(TypePpf, fileSelected)) { + Image img = JSR75.getPPFImage(pathFile, fileSelected); + PPM.dsp.setCurrent(new Viewer(img, this)); + } + P.path = pathFile;*/ + } + else if (cur.equals( L.str[L.cancel])) { + // Отмена + P.path = pathFile; + if(menu[0].equals(L.str[L.saveInThisFolder])) Main.dsp.setCurrent(previousDisplayable); + else Main.dsp.setCurrent(Main.midlet.menu); + } + else if (cur.equals(L.str[L.saveInThisFolder])) { + P.path = pathFile; + } + /*else if (cur.equals(L.str[L.newFolder])) { + // Новая папка + NewFolderForm newFolder = new NewFolderForm(L.str[L.newFolder], this, pathFile); + PPM.dsp.setCurrent(newFolder); + }*/ + } + + /** Загрузка изображений */ + private void loadImages() { + /*Image allimg = new GetImage().loadImages(0);//icons + try { + imageIcon = Image.createImage(allimg, 0, 0, 16, 15, 0); + folderIcon = Image.createImage(allimg, 16, 0, 14, 15, 0); + fileIcon = Image.createImage(allimg, 30, 0, 13, 15, 0); + videoIcon = Image.createImage(allimg, 43, 0, 13, 15, 0); + fontIcon = Image.createImage(allimg, 57, 0, 13, 15, 0); + } catch (Exception ioe) { + }*/ + } + + /** + * Возвратиться в предыдущую папку + */ + private void backDir() { + CursorY = 0; + curFiles = 0; + startPrintFile = 0; + int i = pathFile.lastIndexOf('/', pathFile.length() - 2); + if (i != -1) { + pathFile = pathFile.substring(0, i + 1); + } else { + pathFile = "/"; + return; + } + P.path = pathFile; + update(); + } + + /** + * Перейти в следующую папку или открыть файл + * @param s имя файла / папки + */ + private void nextDir(String s) { + if (s.indexOf("/") != -1) { + pathFile = pathFile + s; + P.path = pathFile; + update(); + curFiles = 0; + startPrintFile = 0; + CursorY = 0; + } else if (getType(TypeMid, s)) { + if(menu[0].equals(L.str[L.saveInThisFolder])) return; + try { + if (Main.midlet.compositionForm != null) { + Main.midlet.compositionForm.releaseMem(); + } + Main.midlet.compositionForm = null; + System.gc(); +// + String openSaveString = pathFile + s; + Main.midlet.compositionForm = new CompositionForm(new MixerMain(), openSaveString); + Main.dsp.setCurrent(Main.midlet.compositionForm); + new Thread(Main.midlet.compositionForm).start(); + + } catch (Exception e) { + /*Alert a = new Alert(Constants.getStringName(13), Constants.getStringName(13) + ":\n" + e.getMessage(), null, null); + display.setCurrent(a); + if (compositionForm != null) { + compositionForm.releaseMem(); + } + compositionForm = null;*/ + } + } + } + + public void keyPressed(int i) { + super.keyPressed(i); + int ga = getGameAction(i); + if (showMenu) { + // Открыто меню - перемещаемся по нему + if (ga==UP) { + curMenu--; + if(curMenu<0) curMenu = menu.length - 1; + } + else if (ga==DOWN) { + curMenu++; + if(curMenu >= menu.length) curMenu = 0; + } + else if (ga==FIRE || ga==RIGHT) selectItem(curMenu); + else if (i == Key.leftSoftKey) showMenu = !showMenu; + } else { + if(i == Key.leftSoftKey) { + showMenu = true; + curMenu = 0; + setMenu(); + } + else if(ga == LEFT || i == Key.rightSoftKey) { + backDir(); + } + else switch(ga) { + case DOWN: cursorDown(); break; + case UP: cursorUp(); break; + case FIRE: + case RIGHT: + nextDir(data[curFiles]); + break; + } + switch (i) { + case KEY_NUM3: + for(int qq=0; qq<10; qq++) cursorUp(); + break; + case KEY_NUM9: + for(int qq=0; qq<10; qq++) cursorDown(); + break; + } + } + repaint(); + } + + protected void pointerPressed(int pix, int piy) { + int y = UI.getSoftBarHeight(); + if (showMenu) { + if(pix<2*y && piy>h-y) { + showMenu = !showMenu; + } + } + if(pix<2*y && piy>h-y) { + showMenu = true; + curMenu = 0; + setMenu(); + }else if(pix>w-2*y && piy>h-y) { + backDir(); + } + repaint(); + } + + + public void keyRepeated(int i) { + keyPressed(i); + } + + private void cursorDown() { + if (data.length > 0) { + final int maxHeight = h - 2 * SH_HEIGHT; + if (curFiles == data.length - 1) { + CursorY = 0; + curFiles = 0; + startPrintFile = 0; + } else if (curFiles > (maxHeight / FONT_HEIGHT - 3)) { + if (CursorY >= (maxHeight - 2 * FONT_HEIGHT)) { + startPrintFile++; + curFiles++; + } else { + curFiles++; + CursorY += FONT_HEIGHT; + } + } else { + CursorY += FONT_HEIGHT; + curFiles++; + } + } + } + + private void cursorUp() { + if (data.length > 0) { + if (curFiles == 0) { + curFiles = data.length - 1; + final int maxHeight = h - 2 * SH_HEIGHT; + if (data.length > (maxHeight / FONT_HEIGHT)) { + startPrintFile = (data.length - maxHeight / FONT_HEIGHT) + 1; + CursorY = (data.length - 1 - startPrintFile) * FONT_HEIGHT; + } else { + CursorY = (data.length - 1) * FONT_HEIGHT; + } + } else if ((CursorY == 0) && (curFiles > 0)) { + startPrintFile--; + curFiles--; + } else if (CursorY > 0) { + CursorY -= FONT_HEIGHT; + curFiles--; + } + } + } + + /** + * Определить принадлежность файла к какому-то типу данных по расширению + * @param type массив расширений данного типа + * @param file имя файла + * @return true - принадлежит + */ + private boolean getType(String[] type, String file) { + for (int i = 0; i < type.length; i++) { + if (file.toLowerCase().endsWith("." + type[i])) { + return true; + } + } + return false; + } + + /** + * Обновить список файлов + */ + private void update() { + data = file.list(pathFile); + numFiles = data.length; + } + +} diff --git a/src/Key.java b/src/Key.java new file mode 100644 index 0000000..2873533 --- /dev/null +++ b/src/Key.java @@ -0,0 +1,85 @@ + + +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +/** + * + * @author sinaz + */ +public class Key { + + public static String Platform = "";//можно убрать если не нужно + public static int leftSoftKey = -6;//ALL Devices + public static int rightSoftKey = -7;//ALL Devices + public static int Clear = -1000;//SonyEricsson & Nokia(S60) + public static int Call = - 1000;// Samsung Z500 & Siemens Devices + public static int Hangup = - 1000;//Siemens Devices (S-Gold) + public static int Back = -1000;//SonyEricsson + public static int InputMode = -1000;//Only Nokia Devices (S60) + + //Only SonyEricsson JP6 + public static int VolPlus = -1000; + public static int VolMinus = -1000; + public static int Camera = -1000; + public static int Focus = -1000; + public static int Snapshot = -1000; + //************************* + + + static { + String microeditionPlatform = System.getProperty("microedition.platform"); + if (microeditionPlatform != null) { + String melc = microeditionPlatform.toLowerCase(); + if (melc.indexOf("ericsson") != -1)//SonyEricsson + { + Clear = -8; + Back = -11; + Call = -10; + //Only SonyEricsson JP6 + VolPlus = -36; + VolMinus = -37; + Camera = -24; + Focus = -25; + Snapshot = -26; + Platform = "Sony Ericsson"; + } else if (melc.indexOf("nokia") != -1)//Nokia Devices (S40) (S60) + { + //Only Nokia Devices (S60) + Clear = -8; + InputMode = -50; + Platform = "Nokia"; + } else {//остальные не выдают фирму,а только марку мобилы например Z500,потому их лучше ловить по классам + try { + Class.forName("com.samsung.util.Vibration");//Samsung + Call = -5;// Samsung Z500 + Platform = "Samsung"; + } catch (Throwable t0) { + + try { + Class.forName("com.siemens.mp.io.file.FileConnection");//Siemens Devices (S-Gold) + leftSoftKey = -1; + rightSoftKey = -4; + Call = -11; + Hangup = -12; + Camera = -20; + Platform = "Siemens"; + } catch (Throwable t1) { + + try { + Class.forName("com.motorola.io.file.FileConnection"); + leftSoftKey = -21; + rightSoftKey = -22; + Call = -10; + //Motorola V300, V500, V525 должны быть софты leftSoftKey = 21;rightSoftKey = 22; + Platform = "Motorola"; + } catch (Throwable t2) { //сюда можно вписать ешё платформу мотороллы с классом com.motorola.io.FileConnection + //но у неё файловая мудацкая + } + } + } + } + } + } +} diff --git a/src/L.java b/src/L.java new file mode 100644 index 0000000..ca6a14b --- /dev/null +++ b/src/L.java @@ -0,0 +1,153 @@ +import java.io.*; +import java.util.Vector; +import midedit.BufDataInputStream; + +/** + * Класс текстовых меток + * @author aNNiMON + */ +public class L { + + /** Номера строк текстовых меток */ + public static final byte + create = 0, + resume = 1, + about = 2, + open = 3, + save = 4, + saveAs = 5, + file = 6, + options = 7, + exit = 8, + RMS = 9, + cancel = 10, + error = 11, + openError = 12, + toolsList = 13, + impossible = 14, + saved = 15, + savingError = 16, + saving = 17, + opening = 18, + chooserError = 19, + updateError = 20, + apiError = 21, + instruments = 22, + menu = 23, + back = 24, + insertNoteWithCurrentAttributes = 25, + noteAttributeHelp = 26, + deleteNote = 27, + undo = 28, + noteVolume = 29, + playFromCurrent = 30, + playNoteOnCursor = 31, + selectNoteAttribute = 32, + changeNoteAttribute = 33, + stop = 34, + navigationOnComposition = 35, + quicknav = 36, + markBegin = 37, + markEnd = 38, + copy = 39, + pasteInsert = 40, + pasteReplace = 41, + pasteOverwrite = 42, + shiftDelete = 43, + clean = 44, + playChannelOnScreen = 45, + playChannelAll = 46, + redo = 47, + addInstrument = 48, + edit = 49, + setInstrument = 50, + delInstrument = 51, + tempoBox = 52, + volumeBox = 53, + meter = 54, + play = 55, + playOrigin = 56, + ok = 57, + upOneLevel = 58, + delete = 59, + chooseFolder = 60, + openFile = 61, + pleaseWait = 62, + updatingList = 63, + saveInThisFolder = 64, + insertTempo = 65, + deleteTempo = 66, + tempo = 67, + time = 68, + seek = 69, + numerator = 70, + denominator = 71, + meterInfo = 72, + delta = 73, + playStop = 74, + playAll = 75, + playScreen = 76, + trackAll = 77, + trackScreen = 78, + mark = 79, + unmark = 80, + modifyBlock = 81, + modifyMode = 82, + paste = 83, + insert = 84, + replace = 85, + blend = 86, + removeSelection = 87, + help = 88, + keymap = 89, + quickCommands = 90, + navigation = 91, + numkeysOptionString = 92, + iconsOptionString = 93; + + + /** Массив текстовых меток */ + public static String[] str, instr; + + /** + * Прочитать языковой ресурс + * @param lang имя локализации (en, ru) + * @param appLang читать языковой ресурс приложения (true), инструментов (false) + */ + public static void readLang(String lang, boolean appLang) { + try { + final String path = (appLang ? "strings" : "instr") + "_"; + System.out.println("/lang/" + path + lang + ".loc"); + BufDataInputStream bdis = new BufDataInputStream(Runtime.getRuntime().getClass().getResourceAsStream("/lang/" + path + lang + ".loc")); + if (!bdis.checkBOM()) { + bdis.close(); + } + char c = ' '; + Vector v = new Vector(); + StringBuffer s; + while (bdis.available() > 0) { + s = new StringBuffer(); + do { + c = bdis.readCharUTF(); + if (c == '\n') { + break; + } + s.append(c); + } while (bdis.available() > 0); + v.addElement(s.toString()); + } + if(appLang) { + str = new String[v.size()]; + v.copyInto(str); + } else { + instr = new String[v.size()]; + v.copyInto(instr); + } + bdis.close(); + v = null; + } catch (IOException ex) { + ex.printStackTrace(); + } + } + +} \ No newline at end of file diff --git a/src/Main.java b/src/Main.java index 42aec16..fbfe548 100644 --- a/src/Main.java +++ b/src/Main.java @@ -5,27 +5,40 @@ import javax.microedition.lcdui.*; import javax.microedition.midlet.*; +import midedit.CompositionForm; +import midedit.MixerModel; /** * @author aNNiMON */ public class Main extends MIDlet { - public Display dsp; + public static Display dsp; public static Main midlet; + public Menu menu; + public MixerModel model; + public CompositionForm compositionForm; + public Main() { midlet = Main.this; dsp = Display.getDisplay(Main.this); } public void startApp() { + Rms.restoreOptions(); + L.readLang(Rms.languageApp, true); + menu = new Menu(); + model = new MixerModel(); + dsp.setCurrent(menu); } public void pauseApp() { } public void destroyApp(boolean ex) { + if(Rms.firstStart) Rms.firstStart = false; + Rms.saveOptions(); notifyDestroyed(); } } diff --git a/src/Menu.java b/src/Menu.java new file mode 100644 index 0000000..2977bab --- /dev/null +++ b/src/Menu.java @@ -0,0 +1,243 @@ +import java.io.IOException; +import javax.microedition.lcdui.*; +import midedit.MixerModel; + +/** + * Меню в программе + * @author aNNiMON + */ +public class Menu extends Canvas { + + /** Кол-во иконок меню */ + private static final int MAX_MENU_ICONS = 9; + /** ID иконок */ + private static final int CREATE_NEW = 0; + private static final int RESUME = 1; + private static final int OPEN = 2; + private static final int SAVE = 3; + private static final int SAVE_AS = 4; + private static final int RMS_FS = 5; + private static final int OPTIONS = 6; + private static final int ABOUT = 7; + private static final int EXIT = 8; + + /** Размер экрана */ + private int w, h; + /** Предыдущий экран, куда будем возвращаться при нажатии Назад */ + private Displayable pr; + + /** Меню */ + private String[] menu; + /** Выделенный пункт меню */ + private int cu = 0; + + /** Иконки */ + private Image[] icons; + + private final int iconsSize; + + private int FileY, CursorY, stFh, startPrintFile; + private int FILE_HEIGHT; + + /** Время для double-клика в touchscreen */ + private long time; + + /** + * Создать меню с типом mode + */ + public Menu() { + setFullScreenMode(true); + w = getWidth(); + h = getHeight(); + readImages(); + iconsSize = icons[0].getHeight(); + // Добавляем пункты + menu = new String[] { + L.str[L.create], + L.str[L.resume], + L.str[L.open], + L.str[L.save], + L.str[L.saveAs], + L.str[L.file], + L.str[L.options], + L.str[L.about], + L.str[L.exit] + }; + FILE_HEIGHT = iconsSize + 2;//P.medPlain.getHeight() + 2; + stFh = P.medPlain.getHeight() + P.medPlain.getHeight() / 2; + CursorY = FileY = startPrintFile = 0; + } + + protected void sizeChanged(int w, int h) { + this.w = getWidth(); + this.h = getHeight(); + super.sizeChanged(w, h); + } + + protected void paint(Graphics g) { + // Очистка экрана + g.setColor(P.backgrnd); + g.fillRect(0, 0, w, h); + + String title = "MidEdit. "+Key.Platform; + UI.drawTitle(g, title); + UI.drawSoftBar(g, L.str[L.ok], L.str[L.exit]); + + g.setFont(P.medBold); + + g.setColor(P.fmback1); + g.translate(0, stFh); + // Курсор + g.setColor(P.obv); + g.fillRect(-1, CursorY, w, FILE_HEIGHT-1); + g.setColor(P.fmbord); + g.drawRect(-1, CursorY-1, w, FILE_HEIGHT); + + FileY = 0; + // Выводим пункты меню + for (int i = startPrintFile; i < menu.length; i++) { + g.setColor(P.fmtextnc); + final String s = menu[i]; + if (FileY == CursorY) { + g.setColor(P.fmshadow); + g.drawString(s, iconsSize + 4, FileY + iconsSize / 4, Graphics.TOP | Graphics.LEFT); + g.setColor(P.fmtextcur); + } + + // Вывод иконок + int id = 0; + if(s.equals(L.str[L.create])) id = CREATE_NEW; + else if(s.equals(L.str[L.resume])) id = RESUME; + else if(s.equals(L.str[L.open])) id = OPEN; + else if(s.equals(L.str[L.save])) id = SAVE; + else if(s.equals(L.str[L.saveAs])) id = SAVE_AS; + else if(s.equals(L.str[L.RMS]) || s.equals(L.str[L.file])) id = RMS_FS; + else if(s.equals(L.str[L.options])) id = OPTIONS; + else if(s.equals(L.str[L.about])) id = ABOUT; + else if(s.equals(L.str[L.exit])) id = EXIT; + + g.drawImage(icons[id], iconsSize + 2, FileY + 1, 24); + + // Название пункта + g.drawString(s, iconsSize + 3, FileY + iconsSize / 4, Graphics.TOP | Graphics.LEFT); + FileY += FILE_HEIGHT; + if(FileY > (h - (stFh*2) - FILE_HEIGHT)) break; + } + g.setColor(0x00); + g.fillRect(-1, FileY+1, w+1, 2); + g.fillRect(-1, -2, w+1, 2); + g.translate(0, -stFh); + } + + /** + * Обработка выбранных пунктов + * @param selected ID выбранного пункта меню + */ + private void selectItem(int selected) { + String v = menu[selected]; + /*if(v.equals(L.str[L.create])) Main.dsp.setCurrent(new CreateNew(this)); + else */if(v.equals(L.str[L.open])) Main.dsp.setCurrent(new FileManager(P.path, MixerModel.getLocalFile())); + /*else if(v.equals(L.str[L.save])) { + } + else if(v.equals(L.str[L.help])) { + TextView tv = new TextView(); + tv.openFile("/lang/help", this, L.str[L.help]); + Main.dsp.setCurrent(tv); + }*/ + else if(v.equals(L.str[L.about])) Main.dsp.setCurrent(new About(this)); + else if(v.equals(L.str[L.exit])) Main.midlet.destroyApp(true); + } + + protected void keyPressed (int key) { + int ga = getGameAction(key); + + if(ga==UP || ga==LEFT) {cursorUp();} + else if(ga==DOWN || ga==RIGHT) {cursorDown();} + else if (ga==FIRE || key==Key.leftSoftKey) selectItem(cu); + else if (key==Key.rightSoftKey) rightSoft(); + repaint(); + } + + protected void keyRepeated (int key) { + keyPressed(key); + } + + private void rightSoft() { + Main.midlet.destroyApp(true); + } + + private void cursorDown() { + if (menu.length > 0) { + final int maxHeight = h - 2 * stFh; + if (cu == menu.length - 1) { + CursorY = 0; + cu = 0; + startPrintFile = 0; + } else if (cu > (maxHeight / FILE_HEIGHT - 3) ) { + if (CursorY >= (maxHeight - 2 * FILE_HEIGHT)) { + startPrintFile++; + cu++; + } else { + cu++; + CursorY += FILE_HEIGHT; + } + } else { + CursorY += FILE_HEIGHT; + cu++; + } + } + } + + private void cursorUp() { + if (menu.length > 0) { + if (cu == 0) { + cu = menu.length - 1; + final int maxHeight = h - 2 * stFh; + if (menu.length > ( (maxHeight - FILE_HEIGHT) / FILE_HEIGHT)) { + startPrintFile = (menu.length - ( maxHeight / FILE_HEIGHT)); + CursorY = (cu - startPrintFile) * FILE_HEIGHT; + } else { + CursorY = cu * FILE_HEIGHT; + } + } else if ((CursorY == 0) && (cu > 0)) { + startPrintFile--; + cu--; + } else if (CursorY > 0) { + CursorY -= FILE_HEIGHT; + cu--; + } + } + } + + /** + * Получить изображения иконок меню + */ + private void readImages() { + icons = new Image[MAX_MENU_ICONS]; + for (int i = 0; i < icons.length; i++) { + try { + icons[i] = Image.createImage("/img/main/"+i+".png"); + } catch (IOException ioe) { + icons[i] = Image.createImage(1, 1); + } + } + } + + protected void pointerPressed(int pix, int piy) { + int q = UI.getSoftBarHeight(); + if(pix<2*q && piy>h-q) selectItem(cu); + else if(pix>w-2*q && piy>h-q) rightSoft(); + else { + int cu1 = cu; + piy -= 2*P.medPlain.getHeight(); + if(piy>0 && piy= 0xc0) { + return cp1251[ich - 192]; + } + return (char) ich; + } + + /** Кодировать символ в windows-1251 */ + public static byte encodeCharCP1251(char ch) { + if (ch > 0 && ch < 128) { + return (byte) ch; + } else if (ch == 0x401) { + return -88; // Ё + } else if (ch == 0x404) { + return -86; // Є + } else if (ch == 0x407) { + return -81; // Ї + } else if (ch == 0x451) { + return -72; // ё + } else if (ch == 0x454) { + return -70; // є + } else if (ch == 0x457) { + return -65; // ї + } + return (byte) ((byte) (ch) + 176); + } +} diff --git a/src/UI.java b/src/UI.java new file mode 100644 index 0000000..15846a5 --- /dev/null +++ b/src/UI.java @@ -0,0 +1,271 @@ +import java.util.Calendar; +import javax.microedition.lcdui.*; + +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +/** + * + * @author aNNiMON + */ +public class UI { + + /** Шрифт заголовков и софт-бара */ + private static final Font smallFont = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL); + /** Высота софт-бара */ + private static final int softBarHeight = smallFont.getHeight() + 2; + + /** + * Отрисовка софт-бара + * @param g контекст графики + * @param left надпись на левом софте + * @param right надпись на правом софте + */ + public static void drawSoftBar(Graphics g, String left, String right) { + final int w = g.getClipWidth(); + final int h = g.getClipHeight() - 1; + final int w2 = w / 2; + drawHGradient(g, P.coldn, P.colup, 0, h - softBarHeight - 1, w2, softBarHeight + 2); + drawHGradient(g, P.colup, P.coldn, w2, h - softBarHeight - 1, w2, softBarHeight + 2); + g.setColor(0); + g.drawLine(0, h - softBarHeight - 2, w, h - softBarHeight - 2); + g.setFont(smallFont); + g.setColor(0xFFFFFF); + g.drawString(left, 3, h, Graphics.LEFT | Graphics.BOTTOM); + g.drawString(right, w - 3, h, Graphics.RIGHT | Graphics.BOTTOM); + g.setColor(P.backgrnd); + g.drawString(getTime(), w2, h, Graphics.HCENTER | Graphics.BOTTOM); + } + + /** + * Отрисовка заголовка + * @param g контекст графики + * @param title надпись заголовка + */ + public static void drawTitle(Graphics g, String title) { + final int w = g.getClipWidth(); + drawVGradient(g, P.colup, P.coldn, 0, 0, w, softBarHeight); + g.setColor(P.colup); + g.drawLine(0, softBarHeight, w, softBarHeight); + g.setFont(smallFont); + g.setColor(0xFFFFFF); + g.drawString(title, w / 2, softBarHeight, Graphics.HCENTER | Graphics.BOTTOM); + } + + + /** + * Отрисовка интерфейса окна + * @param g контекст графики + * @param title надпись заголовка + * @param rightsoft надпись на правом софте + */ + public static void drawMenuInterface(Graphics g, String title, String rightsoft) { + drawTitle(g, title); + drawSoftBar(g, "", rightsoft); + } + + /** + * Отрисовка состояния по массиву (в эффетках) + * @param g контекст графики + * @param dd массив со значениями + */ + public static void drawStatusBar(Graphics g, int[] dd) { + drawStatusBar(g, Math.abs(dd[0]) + dd[1], Math.abs(dd[2]) + Math.abs(dd[0])); + } + + /** + * Отрисовка состояния по массиву (в эффетках) + * @param g контекст графики + * @param cur текущее состояние + * @param all всего + */ + private static void drawStatusBar(Graphics g, int cur, int all) { + int w = g.getClipWidth(); + int h = g.getClipHeight(); + int sw = w / 20; + int sh = h - h / 20; + g.setColor(0x00); + g.drawRect(w - 2 * sw - 1, h/25 - 1, sw + 1, sh + 1); + int curr = (cur * sh) / all; + drawRect(g, P.colup, P.coldn, w - 2 * sw, (h/25 + (sh - curr)), sw, sh - (sh - curr)); + } + + /** + * Получить высоту шрифта. + * @return высота soft- и title- бара + */ + public static int getSoftBarHeight() { + return softBarHeight; + } + + /** + * Получить время + * @return строка с временем вида: HH:MM + */ + private static String getTime() { + StringBuffer sb = new StringBuffer(); + Calendar cal = Calendar.getInstance(); + int tmp = cal.get(Calendar.HOUR_OF_DAY); + if(tmp <= 9) sb.append('0'); + sb.append(tmp); + sb.append(':'); + //Минута + tmp = cal.get(Calendar.MINUTE); + if(tmp <= 9) sb.append('0'); + sb.append(tmp); + return sb.toString(); + } + + /** + * Ортисовка непрозрачного градиента + * @param g контекст графики + * @param color1 верхний цвет градиента + * @param color2 нижний цвет градиента + * @param x1 X + * @param y1 Y + * @param w ширина + * @param h высота + */ + public static void drawRect(Graphics g, int color1, int color2, int x1, int y1, int w, int h) { + // Если цвета одинаковы, то градиент нам не нужен + if(color1 == color2) { + g.setColor(color1); + g.fillRect(x1, y1, w, h); + return; + } else { + drawVGradient(g, color1, color2, x1, y1, w, h); + } + } + + /** + * Ортисовка прозрачного градиента + * @param g контекст графики + * @param color1 верхний цвет градиента + * @param color2 нижний цвет градиента + * @param x1 X + * @param y1 Y + * @param w ширина + * @param h высота + */ + private static void drawRGB(Graphics g, int color1, int color2, int x1, int y1, int w, int h) { + int a1 = (color1 >> 24) & 0xff; + int a2 = (color2 >> 24) & 0xff; + if(a1>253 && a2>253) { + drawRect(g, color1, color2, x1, y1, w, h); + return; + } + + int r1 = (color1 >> 16) & 0xff; + int g1 = (color1 >> 8) & 0xff; + int b1 = color1 & 0xff; + + int r2 = (color2 >> 16) & 0xff; + int g2 = (color2 >> 8) & 0xff; + int b2 = color2 & 0xff; + + int count = h/3; + if (count<0) count=-count; + if (count<8) count = 8; + int crd1, crd2; + + for (int i = count - 1; i >= 0; i--) { + crd1 = i * h / count + y1; + crd2 = (i + 1) * h / count + y1; + if (crd1 == crd2) continue; + int[] pixelArray = new int[w * (crd2 - crd1)]; + int color = (i * (a2 - a1) / (count - 1) + a1) << 24 | + ((i * (r2 - r1) / (count - 1) + r1) << 16) | + ((i * (g2 - g1) / (count - 1) + g1) << 8) | + (i * (b2 - b1) / (count - 1) + b1); + for (int zi = 0; zi < pixelArray.length; zi++) { + pixelArray[zi] = color; + } + g.drawRGB(pixelArray, 0, w, x1, crd1, w, crd2 - crd1, true); + } + } + + /** + * Отрисовка вертикального градиента + * @param graphics контекст графики + * @param rgb1 верхний цвет градиента + * @param rgb2 нижний цвет градиента + * @param xn X + * @param yn Y + * @param wdh ширина + * @param hgt высота + */ + private static void drawVGradient(Graphics graphics, int rgb1, int rgb2, int xn, int yn, int wdh, int hgt) { + // Первый цвет + int r1 = acolor(rgb1, 'r'); + int g1 = acolor(rgb1, 'g'); + int b1 = acolor(rgb1, 'b'); + // Разница между вторым и первым цветом + int deltaR = acolor(rgb2, 'r') - r1; + int deltaG = acolor(rgb2, 'g') - g1; + int deltaB = acolor(rgb2, 'b') - b1; + try { + wdh += xn; + hgt += yn; + final int deltaHeight = hgt - yn - 1; + for (int i = yn; i < hgt; i++) { + int r = r1 + ((i - hgt + 1) * deltaR) / deltaHeight + deltaR; + int g = g1 + ((i - hgt + 1) * deltaG) / deltaHeight + deltaG; + int b = b1 + ((i - hgt + 1) * deltaB) / deltaHeight + deltaB; + graphics.setColor(r, g, b); + graphics.drawLine(xn, i, wdh - 1, i); + } + } catch (Exception ex) { + } + } + + /** + * Отрисовка горизонтального градиента + * @param graphics контекст графики + * @param rgb1 верхний цвет градиента + * @param rgb2 нижний цвет градиента + * @param xn X + * @param yn Y + * @param wdh ширина + * @param hgt высота + */ + private static void drawHGradient(Graphics graphics, int rgb1, int rgb2, int xn, int yn, int wdh, int hgt) { + int r, g, b; + r = g = b = 0; + // Первый цвет + int r1 = acolor(rgb1, 'r'); + int g1 = acolor(rgb1, 'g'); + int b1 = acolor(rgb1, 'b'); + // Разница между вторым и первым цветом + int deltaR = acolor(rgb2, 'r') - r1; + int deltaG = acolor(rgb2, 'g') - g1; + int deltaB = acolor(rgb2, 'b') - b1; + try { + wdh += xn; + hgt += yn; + final int deltaWidth = wdh - xn - 1; + for (int i = xn; i < wdh; i++) { + r = r1 + ((i - wdh + 1) * deltaR) / deltaWidth + deltaR; + g = g1 + ((i - wdh + 1) * deltaG) / deltaWidth + deltaG; + b = b1 + ((i - wdh + 1) * deltaB) / deltaWidth + deltaB; + graphics.setColor(r, g, b); + graphics.drawLine(i, yn, i, hgt - 1); + } + } catch (Exception ex) { + } + } + + /** + * Получить цвет нужного канала в пикселе + * @param argb пиксель + * @param c символьный параметр - название канала (a, r, g, b) + * @return + */ + private static int acolor(int argb, char c) { + if(c=='r') return ((argb >> 16) & 0xff); + else if(c=='g') return ((argb >> 8) & 0xff); + else if(c=='b') return (argb & 0xff); + else if(c=='a') return ((argb >> 24) & 0xff); + else return argb; + } +} diff --git a/src/midedit/Constants.java b/src/midedit/Constants.java index 506251f..29e7b18 100644 --- a/src/midedit/Constants.java +++ b/src/midedit/Constants.java @@ -14,27 +14,7 @@ import java.util.Vector; */ public class Constants { -// private static Hashtable hashInstrums ; - /** - public Constants() - { - //instruments = getInstruments(); -// hashInstrums= new Hashtable(129); -// for(int i=0; i ",getStringName(49), }; static VectorArr instrVectorArr=new VectorArr(Settings.parserInstr.stringResourses, 1, 128); -} -class VectorArr extends Vector { + +static class VectorArr extends Vector { public VectorArr(Object src, int beg, int length) { super(length); setSize(length); @@ -140,3 +120,4 @@ class VectorArr extends Vector { } } +} \ No newline at end of file diff --git a/src/midedit/FileChooser.java b/src/midedit/FileChooser.java index 1b7b5db..2f80ed9 100644 --- a/src/midedit/FileChooser.java +++ b/src/midedit/FileChooser.java @@ -51,9 +51,9 @@ public class FileChooser extends List implements CommandListener, Runnable { if (isSave) { saveThis = new Command(Constants.getStringName(66), Command.SCREEN, 0); this.addCommand(saveThis); - } - else if (MixerModel.isRMSMode) - this.addCommand(delete); + } else if (MixerModel.isRMSMode) + this.addCommand(delete); + this.addCommand(Settings.comCancel); this.setCommandListener(this); updateView(); diff --git a/src/midedit/Settings.java b/src/midedit/Settings.java index 8f4b1d1..575ec9d 100644 --- a/src/midedit/Settings.java +++ b/src/midedit/Settings.java @@ -14,7 +14,7 @@ public class Settings implements CommandListener { //RMSFile rmsFile = new RMSFile(); static String[] langList = {"en", "ru"}; Image[] langImgs = {createImg("/img/en_GB.png"), createImg("/img/ru_RU.png")}, - controlImgs = {createImg("/img/keyPad.png"), createImg("/img/iconsMenu.png")}; + controlImgs = {createImg("/img/keyPad.png"), createImg("/img/icon.png")}; ChoiceGroup langChoice = new ChoiceGroup("Language", 1, langList, langImgs), langInstr = new ChoiceGroup("Instruments Language", 1, langList, langImgs), controlChoice;// = new ChoiceGroup("Controls", 1, controlList, controlImgs); diff --git a/src/midedit/io/AbstractFile.java b/src/midedit/io/AbstractFile.java index c469be2..97dbae4 100644 --- a/src/midedit/io/AbstractFile.java +++ b/src/midedit/io/AbstractFile.java @@ -18,9 +18,8 @@ public abstract class AbstractFile { * * @param pathName * @return - * @throws IOException */ - public abstract String[] list(String pathName) throws IOException; + public abstract String[] list(String pathName); /** * diff --git a/src/midedit/io/JSR75File.java b/src/midedit/io/JSR75File.java index 27941bb..27f2d2e 100644 --- a/src/midedit/io/JSR75File.java +++ b/src/midedit/io/JSR75File.java @@ -18,49 +18,34 @@ public class JSR75File extends AbstractFile { private String lastFileURL = null; /** - * - * @param pathName - * @return - * @throws IOException + * Получить список файлов в папке path + * @param pathName путь к папке + * @return массив с отсортированным списком файлов */ - public String[] list(String pathName) throws IOException { + public String[] list(String pathName) { lastPath = pathName; - Enumeration e; - FileConnection currDir = null; - - - if (pathName.equals("/")) { - e = FileSystemRegistry.listRoots(); - lastPath = "/"; - } else { - currDir = (FileConnection) Connector.open(getPrefix() + pathName); - if (currDir.exists() && currDir.isDirectory()) { - e = currDir.list(); - lastPath = pathName; - } else { - e = FileSystemRegistry.listRoots(); - lastPath = "/"; + Vector vector = new Vector(); + Enumeration en; + try { + FileConnection currDir = null; + // Для получения списка дисков используем FileSystemRegistry + if ("/".equals(pathName)) en = FileSystemRegistry.listRoots(); + else { + // Для остальных папок - обычный FileConnection + currDir = (FileConnection) Connector.open("file://" + pathName, Connector.READ); + en = currDir.list(); } + // Перемещаем список в вектор + while(en.hasMoreElements()) { + String s1 = (String) en.nextElement(); + vector.addElement(s1); + } + if (currDir != null) currDir.close(); + } catch (IOException ion) { + ion.printStackTrace(); } - - - if (e == null) { - throw new IOException("e==null"); - } - - Vector v = new Vector(); - for (; e.hasMoreElements();) { - v.addElement(e.nextElement()); - } - String[] listFile = new String[v.size()]; - int i; - Enumeration enumer; - for (i = 0, enumer = v.elements(); i < listFile.length; ++i) { - listFile[i] = (String) (enumer.nextElement()); - } - - - return listFile; + // Сортируем и возвращаем список + return bubbleSort(vector); } /** @@ -281,4 +266,50 @@ public class JSR75File extends AbstractFile { public String getAns() { return "save ok"; } + + /** + * Пузырьковая сортировка. + * Сортирует по имени, а потом подымает папки в начало + * @param files вектор со списком имён файлов и папок + * @param reverse true - сортировка по убыванию + * @return + */ + private static String[] bubbleSort(Vector files) { + String tmp; + for (int i = files.size() - 1; i >= 0; i--) { + for (int j = 0; j < i; j++) { + if ((tmp = (String) files.elementAt(j)).toLowerCase().compareTo(((String) files.elementAt(j + 1)).toLowerCase()) > 0) { + files.setElementAt((String) files.elementAt(j + 1), j); + files.setElementAt(tmp, j + 1); + } + } + } + String[] arr = sortFiles(files); + return arr; + } + + /** + * Сортировка файлов. + * Папки поднимаются в начало списка, остальные файлы не трогаются. + * @param files вектор со списком имён файлов и папок + * @return массив с отсортированным списком + */ + private static String[] sortFiles(Vector files) { + int length = files.size(); + String[] out = new String[length]; + int i = 0; + for (int j = 0; j < length; j++) { + if (((String)files.elementAt(j)).indexOf("/") != -1) { + out[i] = ((String)files.elementAt(j)); + i++; + } + } + for (int k = 0; k < length; k++) { + if (((String)files.elementAt(k)).indexOf("/") == -1) { + out[i] = ((String)files.elementAt(k)); + i++; + } + } + return out; + } } diff --git a/src/midedit/io/RMSFile.java b/src/midedit/io/RMSFile.java index f5757b7..f88103b 100644 --- a/src/midedit/io/RMSFile.java +++ b/src/midedit/io/RMSFile.java @@ -16,7 +16,7 @@ public class RMSFile extends AbstractFile { private RecordStore curRecordStore = null; private int recordID = 0; - public String[] list(String pathName) throws IOException { + public String[] list(String pathName) { String[] fileList = RecordStore.listRecordStores(); return fileList; } diff --git a/src/text.txt b/src/text.txt index 6506a98..7917d24 100644 --- a/src/text.txt +++ b/src/text.txt @@ -8,4 +8,5 @@ MIDedit 2.1 / 3.0 ****** При первом запуске - настройки +Help в aNMPWR player.realize \ No newline at end of file